diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 427548f..2593caa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ macos-11, macos-12, macos-13 ] + os: [ macos-12, macos-13, macos-14 ] rust: [ nightly, stable ] steps: @@ -25,8 +25,8 @@ jobs: toolchain: ${{ matrix.rust }} override: true - - name: Build and run the echo server - run: cd examples/echo-server && make && make install + - name: Build, run, and test the echo agent and daemon + run: cd examples && make test - name: Run cargo test uses: actions-rs/cargo@v1 diff --git a/.gitignore b/.gitignore index 25f27e2..088ba6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # Generated by Cargo # will have compiled files and executables /target/ -/examples/echo-server/com.example.echo # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..9935e38 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,31 @@ +all: build + +.PHONY: build +build: + cargo build + +.PHONY: test +test: install + cd client && cargo run + +.PHONY: install +install: build + sudo mkdir -p /Library/PrivilegedHelperTools/ + sudo cp ../target/debug/echo-server /Library/PrivilegedHelperTools/echo-daemon + sudo cp echo-server/echo-daemon.plist /Library/LaunchDaemons/ + sudo launchctl load /Library/LaunchDaemons/echo-daemon.plist + + sudo mkdir -p /usr/local/bin + sudo cp echo-server/echo-agent.plist /Library/LaunchAgents/ + sudo cp ../target/debug/echo-server /usr/local/bin/echo-agent + launchctl load /Library/LaunchAgents/echo-agent.plist + +.PHONY: uninstall +uninstall: + sudo launchctl unload /Library/LaunchDaemons/echo-daemon.plist + sudo rm -f /Library/LaunchDaemons/echo-daemon.plist + sudo rm -f /Library/PrivilegedHelperTools/echo-daemon + + launchctl unload /Library/LaunchAgents/echo-agent.plist + sudo rm -f /Library/LaunchAgents/echo-agent.plist + sudo rm -f /usr/local/bin/echo-agent diff --git a/examples/client/Cargo.toml b/examples/client/Cargo.toml index 393e647..7fbe76c 100644 --- a/examples/client/Cargo.toml +++ b/examples/client/Cargo.toml @@ -1,11 +1,8 @@ [package] name = "client" -version = "0.1.0" -authors = ["Steven Joruk "] -edition = "2018" -publish = false +edition = "2021" [dependencies] futures = { version = "0.3" } -tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1", features = ["macros", "time", "rt-multi-thread"] } xpc-connection = { path = "../../xpc-connection" } diff --git a/examples/client/src/main.rs b/examples/client/src/main.rs index 421051d..473ea92 100644 --- a/examples/client/src/main.rs +++ b/examples/client/src/main.rs @@ -1,23 +1,31 @@ use futures::stream::StreamExt; -use std::{collections::HashMap, error::Error, ffi::CString}; +use std::{collections::HashMap, ffi::CStr, time::Duration}; use xpc_connection::{Message, XpcClient}; #[tokio::main] -async fn main() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; +async fn main() { + send_with_reply(c"echo-agent", false).await; + send_with_reply(c"echo-daemon", true).await; +} + +async fn send_with_reply(mach_port_name: &CStr, privileged: bool) { + println!("Attempting to connect to {mach_port_name:?}"); - println!("Attempting to connect to {:?}", mach_port_name); - let mut client = XpcClient::connect(&mach_port_name); + let mut client = if privileged { + XpcClient::connect_privileged(mach_port_name) + } else { + XpcClient::connect_unprivileged(mach_port_name) + }; let mut dictionary = HashMap::new(); - dictionary.insert(CString::new("hello")?, Message::Int64(2)); + dictionary.insert(c"hello".to_owned(), Message::Int64(2)); println!("Sending a message"); client.send_message(Message::Dictionary(dictionary)); - if let Some(message) = client.next().await { - println!("Client received message {:?}", message); - } + let message = tokio::time::timeout(Duration::from_secs(1), client.next()) + .await + .expect("No reply received"); - Ok(()) + println!("Client received message {:?}", message); } diff --git a/examples/echo-server/Cargo.toml b/examples/echo-server/Cargo.toml index 95dce79..526b9a3 100644 --- a/examples/echo-server/Cargo.toml +++ b/examples/echo-server/Cargo.toml @@ -1,9 +1,6 @@ [package] name = "echo-server" -version = "0.1.0" -authors = ["Steven Joruk "] -edition = "2018" -publish = false +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/examples/echo-server/Makefile b/examples/echo-server/Makefile deleted file mode 100644 index 974e463..0000000 --- a/examples/echo-server/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -all: ../../target/debug/echo-server - -../../target/debug/echo-server: - cargo build - -install: ../../target/debug/echo-server - # GitHub's runners don't have this directory by default. - sudo mkdir -p /Library/PrivilegedHelperTools/ - sudo cp ../../target/debug/echo-server /Library/PrivilegedHelperTools/com.example.echo - sudo cp com.example.echo.plist /Library/LaunchDaemons/ - sudo launchctl load /Library/LaunchDaemons/com.example.echo.plist - -uninstall: - sudo launchctl unload /Library/LaunchDaemons/com.example.echo.plist - sudo rm /Library/PrivilegedHelperTools/com.example.echo - sudo rm /Library/LaunchDaemons/com.example.echo.plist diff --git a/examples/echo-server/com.example.echo.plist b/examples/echo-server/echo-agent.plist similarity index 53% rename from examples/echo-server/com.example.echo.plist rename to examples/echo-server/echo-agent.plist index 002eefa..0e42285 100644 --- a/examples/echo-server/com.example.echo.plist +++ b/examples/echo-server/echo-agent.plist @@ -3,17 +3,22 @@ Label - com.example.echo + echo-agent MachServices - com.example.echo + echo-agent Program - /Library/PrivilegedHelperTools/com.example.echo + /usr/local/bin/echo-agent + ProgramArguments + + /usr/local/bin/echo-agent + echo-agent + StandardOutPath - /var/log/com.example.echo.log + /tmp/echo-agent.log StandardErrorPath - /var/log/com.example.echo.log + /tmp/echo-agent.log diff --git a/examples/echo-server/echo-daemon.plist b/examples/echo-server/echo-daemon.plist new file mode 100644 index 0000000..f9f8a5d --- /dev/null +++ b/examples/echo-server/echo-daemon.plist @@ -0,0 +1,24 @@ + + + + + Label + echo-daemon + MachServices + + echo-daemon + + + Program + /Library/PrivilegedHelperTools/echo-daemon + ProgramArguments + + /usr/local/bin/echo-daemon + echo-daemon + + StandardOutPath + /tmp/echo-daemon.log + StandardErrorPath + /tmp/echo-daemon.log + + diff --git a/examples/echo-server/src/main.rs b/examples/echo-server/src/main.rs index a99fe39..39f4d03 100644 --- a/examples/echo-server/src/main.rs +++ b/examples/echo-server/src/main.rs @@ -1,7 +1,7 @@ use core_foundation::{base::TCFType, data::CFData}; use futures::stream::StreamExt; use security_framework::os::macos::code_signing::{Flags, GuestAttributes, SecCode}; -use std::{error::Error, ffi::CString}; +use std::ffi::CString; use xpc_connection::{Message, MessageError, XpcClient, XpcListener}; fn get_code_object_for_client(client: &XpcClient) -> SecCode { @@ -28,31 +28,9 @@ fn validate_client_by_code_signing_requirement(client: &XpcClient) -> bool { false } -fn validate_client_by_path(client: &XpcClient) -> bool { - if get_code_object_for_client(client) - .path(Flags::NONE) - .unwrap() - // It'd be better to use to_path - .get_string() - .to_string() - // This is insecure, it's just so the tests can be run from anywhere - .contains("message_round_trip") - { - println!("The client was validated using its path"); - return true; - } - - println!("The client's path doesn't contain 'message_round_trip'"); - false -} - async fn handle_client(mut client: XpcClient) { println!("New connection"); - if !validate_client_by_path(&client) { - return; - } - loop { match client.next().await { None => { @@ -72,13 +50,16 @@ async fn handle_client(mut client: XpcClient) { } #[tokio::main(flavor = "multi_thread")] -async fn main() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; +async fn main() { + let mach_port_name = CString::new( + std::env::args() + .nth(1) + .expect("Usage: echo-server ") + .as_str(), + ) + .expect("Failed to convert the mach port name to a CString"); - println!( - "Waiting for new connections on {:?}", - mach_port_name.to_string_lossy() - ); + println!("Waiting for new connections on {mach_port_name:?}",); let mut listener = XpcListener::listen(&mach_port_name); @@ -87,6 +68,4 @@ async fn main() -> Result<(), Box> { } println!("Server is shutting down"); - - Ok(()) } diff --git a/xpc-connection/Cargo.toml b/xpc-connection/Cargo.toml index 5b62108..ec92a34 100644 --- a/xpc-connection/Cargo.toml +++ b/xpc-connection/Cargo.toml @@ -1,8 +1,8 @@ [package] authors = ["Dylan Frankland "] name = "xpc-connection" -version = "0.2.3" -edition = "2018" +version = "0.3.0" +edition = "2021" license = "MIT" description = "XPC connection bindings for Rust" homepage = "https://github.com/dfrankland/xpc-connection-rs" diff --git a/xpc-connection/src/lib.rs b/xpc-connection/src/lib.rs index fb60388..9e4d026 100644 --- a/xpc-connection/src/lib.rs +++ b/xpc-connection/src/lib.rs @@ -201,9 +201,33 @@ impl XpcClient { } /// The connection isn't established until the first call to `send_message`. + /// + /// This is an alias for [`XpcClient::connect_privileged`]. + #[deprecated( + since = "0.3.0", + note = "Use connect_privileged or connect_unprivileged" + )] pub fn connect(name: impl AsRef) -> Self { + Self::connect_privileged(name) + } + + /// The connection isn't established until the first call to `send_message`. + /// + /// Connects to a privileged mach port, i.e. a launch daemon. + pub fn connect_privileged(name: impl AsRef) -> Self { + Self::connect_with_flags(name, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED as u64) + } + + /// The connection isn't established until the first call to `send_message`. + /// + /// Connects to an unprivileged mach port, i.e. a launch agent. + pub fn connect_unprivileged(name: impl AsRef) -> Self { + Self::connect_with_flags(name, 0) + } + + /// The connection isn't established until the first call to `send_message`. + fn connect_with_flags(name: impl AsRef, flags: u64) -> Self { let name = name.as_ref(); - let flags = XPC_CONNECTION_MACH_SERVICE_PRIVILEGED as u64; let connection = unsafe { xpc_connection_create_mach_service(name.as_ptr(), std::ptr::null_mut(), flags) }; @@ -247,15 +271,14 @@ impl XpcClient { mod tests { use super::*; use futures::{executor::block_on, StreamExt}; - use std::{collections::HashMap, ffi::CString}; + use std::collections::HashMap; use xpc_connection_sys::xpc_connection_cancel; // This also tests that the event handler block is only freed once, as a // double free is possible if the block isn't copied on to the heap. #[test] fn event_handler_receives_error_on_close() { - let mach_port_name = CString::new("com.apple.blued").unwrap(); - let mut client = XpcClient::connect(&mach_port_name); + let mut client = XpcClient::connect_privileged(c"com.apple.blued"); // Cancelling the connection will cause the event handler to be called // with an error message. This will happen under normal circumstances, @@ -268,21 +291,20 @@ mod tests { } #[test] - fn stream_closed_on_drop() -> Result<(), Box> { - let mach_port_name = CString::new("com.apple.blued")?; - let mut client = XpcClient::connect(&mach_port_name); + fn stream_closed_on_drop() { + let mut client = XpcClient::connect_privileged(c"com.apple.blued"); let message = Message::Dictionary({ let mut dictionary = HashMap::new(); - dictionary.insert(CString::new("kCBMsgId")?, Message::Int64(1)); + dictionary.insert(c"kCBMsgId".to_owned(), Message::Int64(1)); dictionary.insert( - CString::new("kCBMsgArgs")?, + c"kCBMsgArgs".to_owned(), Message::Dictionary({ let mut temp = HashMap::new(); - temp.insert(CString::new("kCBMsgArgAlert")?, Message::Int64(1)); + temp.insert(c"kCBMsgArgAlert".to_owned(), Message::Int64(1)); temp.insert( - CString::new("kCBMsgArgName")?, - Message::String(CString::new("rust")?), + c"kCBMsgArgName".to_owned(), + Message::String(c"rust".to_owned()), ); temp }), @@ -312,7 +334,7 @@ mod tests { // from blued before the connection is cancelled, but it's // safe to say it should be less than 5. assert!(count < 5); - return Ok(()); + return; } } } diff --git a/xpc-connection/tests/message_round_trip.rs b/xpc-connection/tests/message_round_trip.rs index 2613f45..251ef8f 100644 --- a/xpc-connection/tests/message_round_trip.rs +++ b/xpc-connection/tests/message_round_trip.rs @@ -2,7 +2,6 @@ use futures::{executor::block_on, StreamExt}; use std::{ collections::HashMap, error::Error, - ffi::CString, fs::File, os::unix::prelude::{FromRawFd, IntoRawFd, MetadataExt}, time::{Duration, SystemTime}, @@ -11,12 +10,11 @@ use xpc_connection::{Message, XpcClient}; #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_int64() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_int64() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); let mut output = HashMap::new(); - let key = CString::new("K")?; + let key = c"K".to_owned(); output.insert(key.clone(), Message::Int64(1)); con.send_message(Message::Dictionary(output)); @@ -24,7 +22,7 @@ fn send_and_receive_int64() -> Result<(), Box> { if let Some(Message::Dictionary(d)) = message { let input = d.get(&key); if let Some(Message::Int64(1)) = input { - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -35,13 +33,12 @@ fn send_and_receive_int64() -> Result<(), Box> { #[tokio::test] #[ignore = "This test requires the echo server to be running"] -async fn send_and_receive_string() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +async fn send_and_receive_string() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); let mut output = HashMap::new(); - let key = CString::new("K")?; - let value = CString::new("V")?; + let key = c"K".to_owned(); + let value = c"V".to_owned(); output.insert(key.clone(), Message::String(value.clone())); con.send_message(Message::Dictionary(output)); @@ -51,7 +48,7 @@ async fn send_and_receive_string() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::String(s)) = input { assert_eq!(s, &value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); } @@ -62,13 +59,12 @@ async fn send_and_receive_string() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_dictionary() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_dictionary() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); let mut output = HashMap::new(); - let outer_key = CString::new("O")?; - let inner_key = CString::new("I")?; + let outer_key = c"O".to_owned(); + let inner_key = c"I".to_owned(); output.insert( outer_key.clone(), Message::Dictionary({ @@ -85,7 +81,7 @@ fn send_and_receive_dictionary() -> Result<(), Box> { let inner_dictionary = outer_hashmap.get(&outer_key); if let Some(Message::Dictionary(inner_hashmap)) = inner_dictionary { if let Some(Message::Int64(1)) = inner_hashmap.get(&inner_key) { - return Ok(()); + return; } panic!("Received unexpected value: {:?}", inner_hashmap); @@ -99,12 +95,11 @@ fn send_and_receive_dictionary() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_array() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_array() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); let mut output = HashMap::new(); - let key = CString::new("K")?; + let key = c"K".to_owned(); output.insert(key.clone(), Message::Array(vec![Message::Int64(1)])); con.send_message(Message::Dictionary(output)); @@ -114,7 +109,7 @@ fn send_and_receive_array() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Array(a)) = input { if let Message::Int64(1) = a[0] { - return Ok(()); + return; } panic!("Received unexpected value: {:?}", a); @@ -128,11 +123,10 @@ fn send_and_receive_array() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_data() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_data() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = vec![0, 1]; let mut output = HashMap::new(); output.insert(key.clone(), Message::Data(value.clone())); @@ -144,7 +138,7 @@ fn send_and_receive_data() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Data(v)) = input { assert_eq!(*v, value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -155,11 +149,10 @@ fn send_and_receive_data() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_uint64() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_uint64() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = 0x2d13772f7f30cc5d_u64; let mut output = HashMap::new(); @@ -172,7 +165,7 @@ fn send_and_receive_uint64() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Uint64(v)) = input { assert_eq!(*v, value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -183,11 +176,10 @@ fn send_and_receive_uint64() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_uuid() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_uuid() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut output = HashMap::new(); @@ -200,7 +192,7 @@ fn send_and_receive_uuid() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Uuid(v)) = input { assert_eq!(*v, value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -212,10 +204,9 @@ fn send_and_receive_uuid() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] fn send_and_receive_fd() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let original = File::create("/tmp/a")?; let original_inode = original.metadata()?.ino(); @@ -241,11 +232,10 @@ fn send_and_receive_fd() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_double() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_double() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = 1.23456789_f64; let mut output = HashMap::new(); @@ -258,7 +248,7 @@ fn send_and_receive_double() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Double(v)) = input { assert!((*v - value).abs() < std::f64::EPSILON); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -269,11 +259,10 @@ fn send_and_receive_double() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_bool() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_bool() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = true; let mut output = HashMap::new(); @@ -286,7 +275,7 @@ fn send_and_receive_bool() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Bool(v)) = input { assert_eq!(*v, value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -297,11 +286,10 @@ fn send_and_receive_bool() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_date() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_date() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = SystemTime::now(); let mut output = HashMap::new(); @@ -314,7 +302,7 @@ fn send_and_receive_date() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Date(v)) = input { assert_eq!(*v, value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -325,11 +313,10 @@ fn send_and_receive_date() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_negative_date() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_negative_date() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = SystemTime::UNIX_EPOCH - Duration::from_secs(90); let mut output = HashMap::new(); @@ -342,7 +329,7 @@ fn send_and_receive_negative_date() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Date(v)) = input { assert_eq!(*v, value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -353,11 +340,10 @@ fn send_and_receive_negative_date() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn send_and_receive_null() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn send_and_receive_null() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let mut output = HashMap::new(); output.insert(key.clone(), Message::Null); @@ -368,7 +354,7 @@ fn send_and_receive_null() -> Result<(), Box> { if let Some(Message::Dictionary(d)) = message { let input = d.get(&key); if matches!(input, Some(Message::Null)) { - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input); @@ -379,11 +365,10 @@ fn send_and_receive_null() -> Result<(), Box> { #[test] #[ignore = "This test requires the echo server to be running"] -fn connect_and_disconnect() -> Result<(), Box> { - let mach_port_name = CString::new("com.example.echo")?; - let mut con = XpcClient::connect(mach_port_name); +fn connect_and_disconnect() { + let mut con = XpcClient::connect_privileged(c"echo-daemon"); - let key = CString::new("K")?; + let key = c"K".to_owned(); let value = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut output = HashMap::new(); @@ -396,7 +381,7 @@ fn connect_and_disconnect() -> Result<(), Box> { let input = d.get(&key); if let Some(Message::Uuid(v)) = input { assert_eq!(*v, value); - return Ok(()); + return; } panic!("Received unexpected value: {:?}", input);