mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 14:36:16 +01:00
Use platform-independent socket for FFI
Windows is truly awful Remove config.toml
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1154,6 +1154,7 @@ dependencies = [
|
|||||||
"simplelog",
|
"simplelog",
|
||||||
"tokio",
|
"tokio",
|
||||||
"ureq",
|
"ureq",
|
||||||
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ libc = "0.2.171"
|
|||||||
plist = "1.7.1"
|
plist = "1.7.1"
|
||||||
plist_ffi = "0.1.3"
|
plist_ffi = "0.1.3"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
windows-sys = { version = "0.60", features = ["Win32_Networking_WinSock"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
aws-lc = ["idevice/aws-lc"]
|
aws-lc = ["idevice/aws-lc"]
|
||||||
ring = ["idevice/ring"]
|
ring = ["idevice/ring"]
|
||||||
|
|||||||
27
ffi/build.rs
27
ffi/build.rs
@@ -2,16 +2,35 @@
|
|||||||
|
|
||||||
use std::{env, fs::OpenOptions, io::Write};
|
use std::{env, fs::OpenOptions, io::Write};
|
||||||
|
|
||||||
|
const HEADER: &str = r#"// Jackson Coxson
|
||||||
|
// Bindings to idevice - https://github.com/jkcoxson/idevice
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
typedef int idevice_socklen_t;
|
||||||
|
typedef struct sockaddr idevice_sockaddr;
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
typedef socklen_t idevice_socklen_t;
|
||||||
|
typedef struct sockaddr idevice_sockaddr;
|
||||||
|
#endif
|
||||||
|
"#;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||||
|
|
||||||
cbindgen::Builder::new()
|
cbindgen::Builder::new()
|
||||||
.with_crate(crate_dir)
|
.with_crate(crate_dir)
|
||||||
.with_header(
|
.with_header(HEADER)
|
||||||
"// Jackson Coxson\n// Bindings to idevice - https://github.com/jkcoxson/idevice",
|
|
||||||
)
|
|
||||||
.with_language(cbindgen::Language::C)
|
.with_language(cbindgen::Language::C)
|
||||||
.with_sys_include("sys/socket.h")
|
.with_include_guard("IDEVICE_H")
|
||||||
|
.exclude_item("idevice_socklen_t")
|
||||||
|
.exclude_item("idevice_sockaddr")
|
||||||
.generate()
|
.generate()
|
||||||
.expect("Unable to generate bindings")
|
.expect("Unable to generate bindings")
|
||||||
.write_to_file("idevice.h");
|
.write_to_file("idevice.h");
|
||||||
|
|||||||
@@ -136,22 +136,23 @@ pub unsafe extern "C" fn idevice_new(
|
|||||||
/// `addr` must be a valid sockaddr
|
/// `addr` must be a valid sockaddr
|
||||||
/// `label` must be a valid null-terminated C string
|
/// `label` must be a valid null-terminated C string
|
||||||
/// `idevice` must be a valid, non-null pointer to a location where the handle will be stored
|
/// `idevice` must be a valid, non-null pointer to a location where the handle will be stored
|
||||||
|
#[cfg(unix)]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub unsafe extern "C" fn idevice_new_tcp_socket(
|
pub unsafe extern "C" fn idevice_new_tcp_socket(
|
||||||
addr: *const libc::sockaddr,
|
addr: *const idevice_sockaddr,
|
||||||
addr_len: libc::socklen_t,
|
addr_len: idevice_socklen_t,
|
||||||
label: *const c_char,
|
label: *const c_char,
|
||||||
idevice: *mut *mut IdeviceHandle,
|
idevice: *mut *mut IdeviceHandle,
|
||||||
) -> *mut IdeviceFfiError {
|
) -> *mut IdeviceFfiError {
|
||||||
if addr.is_null() {
|
if addr.is_null() || label.is_null() || idevice.is_null() {
|
||||||
log::error!("socket addr null pointer");
|
log::error!("null pointer(s) to idevice_new_tcp_socket");
|
||||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||||
}
|
}
|
||||||
|
let addr = addr as *const SockAddr;
|
||||||
|
|
||||||
// Convert C string to Rust string
|
|
||||||
let label = match unsafe { CStr::from_ptr(label).to_str() } {
|
let label = match unsafe { CStr::from_ptr(label).to_str() } {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
|
Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
|
||||||
};
|
};
|
||||||
|
|
||||||
let addr = match util::c_socket_to_rust(addr, addr_len) {
|
let addr = match util::c_socket_to_rust(addr, addr_len) {
|
||||||
@@ -159,9 +160,10 @@ pub unsafe extern "C" fn idevice_new_tcp_socket(
|
|||||||
Err(e) => return ffi_err!(e),
|
Err(e) => return ffi_err!(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
let device: Result<idevice::Idevice, idevice::IdeviceError> = RUNTIME.block_on(async move {
|
let device = RUNTIME.block_on(async move {
|
||||||
Ok(idevice::Idevice::new(
|
let stream = tokio::net::TcpStream::connect(addr).await?;
|
||||||
Box::new(tokio::net::TcpStream::connect(addr).await?),
|
Ok::<idevice::Idevice, idevice::IdeviceError>(idevice::Idevice::new(
|
||||||
|
Box::new(stream),
|
||||||
label,
|
label,
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
@@ -170,7 +172,7 @@ pub unsafe extern "C" fn idevice_new_tcp_socket(
|
|||||||
Ok(dev) => {
|
Ok(dev) => {
|
||||||
let boxed = Box::new(IdeviceHandle(dev));
|
let boxed = Box::new(IdeviceHandle(dev));
|
||||||
unsafe { *idevice = Box::into_raw(boxed) };
|
unsafe { *idevice = Box::into_raw(boxed) };
|
||||||
null_mut()
|
std::ptr::null_mut()
|
||||||
}
|
}
|
||||||
Err(e) => ffi_err!(e),
|
Err(e) => ffi_err!(e),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
// Jackson Coxson
|
// Jackson Coxson
|
||||||
|
|
||||||
use idevice::provider::{IdeviceProvider, TcpProvider, UsbmuxdProvider};
|
use idevice::provider::{IdeviceProvider, TcpProvider, UsbmuxdProvider};
|
||||||
|
use std::net::IpAddr;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::{ffi::CStr, ptr::null_mut};
|
use std::{ffi::CStr, ptr::null_mut};
|
||||||
|
|
||||||
|
use crate::util::{SockAddr, idevice_sockaddr};
|
||||||
use crate::{IdeviceFfiError, ffi_err, usbmuxd::UsbmuxdAddrHandle, util};
|
use crate::{IdeviceFfiError, ffi_err, usbmuxd::UsbmuxdAddrHandle, util};
|
||||||
|
|
||||||
pub struct IdeviceProviderHandle(pub Box<dyn IdeviceProvider>);
|
pub struct IdeviceProviderHandle(pub Box<dyn IdeviceProvider>);
|
||||||
@@ -24,33 +26,27 @@ pub struct IdeviceProviderHandle(pub Box<dyn IdeviceProvider>);
|
|||||||
/// `pairing_file` is consumed must never be used again
|
/// `pairing_file` is consumed must never be used again
|
||||||
/// `label` must be a valid Cstr
|
/// `label` must be a valid Cstr
|
||||||
/// `provider` must be a valid, non-null pointer to a location where the handle will be stored
|
/// `provider` must be a valid, non-null pointer to a location where the handle will be stored
|
||||||
#[cfg(feature = "tcp")]
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub unsafe extern "C" fn idevice_tcp_provider_new(
|
pub unsafe extern "C" fn idevice_tcp_provider_new(
|
||||||
ip: *const libc::sockaddr,
|
ip: *const idevice_sockaddr,
|
||||||
pairing_file: *mut crate::pairing_file::IdevicePairingFile,
|
pairing_file: *mut crate::pairing_file::IdevicePairingFile,
|
||||||
label: *const c_char,
|
label: *const c_char,
|
||||||
provider: *mut *mut IdeviceProviderHandle,
|
provider: *mut *mut IdeviceProviderHandle,
|
||||||
) -> *mut IdeviceFfiError {
|
) -> *mut IdeviceFfiError {
|
||||||
if ip.is_null() || label.is_null() || provider.is_null() {
|
let ip = ip as *const SockAddr;
|
||||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
let addr: IpAddr = match util::c_addr_to_rust(ip) {
|
||||||
}
|
|
||||||
|
|
||||||
let addr = match util::c_addr_to_rust(ip) {
|
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(e) => {
|
Err(e) => return ffi_err!(e),
|
||||||
return ffi_err!(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let label = match unsafe { CStr::from_ptr(label) }.to_str() {
|
|
||||||
Ok(l) => l.to_string(),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Invalid label string: {e:?}");
|
|
||||||
return ffi_err!(IdeviceError::FfiInvalidString);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let label = match unsafe { CStr::from_ptr(label).to_str() } {
|
||||||
|
Ok(s) => s.to_string(),
|
||||||
|
Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
|
||||||
|
};
|
||||||
|
|
||||||
|
// consume the pairing file on success
|
||||||
let pairing_file = unsafe { Box::from_raw(pairing_file) };
|
let pairing_file = unsafe { Box::from_raw(pairing_file) };
|
||||||
|
|
||||||
let t = TcpProvider {
|
let t = TcpProvider {
|
||||||
addr,
|
addr,
|
||||||
pairing_file: pairing_file.0,
|
pairing_file: pairing_file.0,
|
||||||
@@ -59,7 +55,7 @@ pub unsafe extern "C" fn idevice_tcp_provider_new(
|
|||||||
|
|
||||||
let boxed = Box::new(IdeviceProviderHandle(Box::new(t)));
|
let boxed = Box::new(IdeviceProviderHandle(Box::new(t)));
|
||||||
unsafe { *provider = Box::into_raw(boxed) };
|
unsafe { *provider = Box::into_raw(boxed) };
|
||||||
null_mut()
|
std::ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Frees an IdeviceProvider handle
|
/// Frees an IdeviceProvider handle
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
IdeviceFfiError, IdeviceHandle, IdevicePairingFile, RUNTIME, ffi_err, util::c_socket_to_rust,
|
IdeviceFfiError, IdeviceHandle, IdevicePairingFile, RUNTIME, ffi_err,
|
||||||
|
util::{SockAddr, c_socket_to_rust, idevice_sockaddr, idevice_socklen_t},
|
||||||
};
|
};
|
||||||
use idevice::{
|
use idevice::{
|
||||||
IdeviceError,
|
IdeviceError,
|
||||||
@@ -32,28 +33,33 @@ pub struct UsbmuxdDeviceHandle(pub UsbmuxdDevice);
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// `addr` must be a valid sockaddr
|
/// `addr` must be a valid sockaddr
|
||||||
/// `usbmuxd_connection` must be a valid, non-null pointer to a location where the handle will be stored
|
/// `usbmuxd_connection` must be a valid, non-null pointer to a location where the handle will be stored
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
pub unsafe extern "C" fn idevice_usbmuxd_new_tcp_connection(
|
pub unsafe extern "C" fn idevice_usbmuxd_new_tcp_connection(
|
||||||
addr: *const libc::sockaddr,
|
addr: *const idevice_sockaddr,
|
||||||
addr_len: libc::socklen_t,
|
addr_len: idevice_socklen_t,
|
||||||
tag: u32,
|
tag: u32,
|
||||||
usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle,
|
out: *mut *mut UsbmuxdConnectionHandle,
|
||||||
) -> *mut IdeviceFfiError {
|
) -> *mut IdeviceFfiError {
|
||||||
let addr = match c_socket_to_rust(addr, addr_len) {
|
if addr.is_null() || out.is_null() {
|
||||||
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinterpret as the real platform sockaddr for parsing
|
||||||
|
let addr = addr as *const SockAddr;
|
||||||
|
|
||||||
|
let addr = match c_socket_to_rust(addr, addr_len as _) {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return ffi_err!(e),
|
Err(e) => return ffi_err!(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
let res: Result<UsbmuxdConnection, IdeviceError> = RUNTIME.block_on(async move {
|
let res = RUNTIME.block_on(async move {
|
||||||
let stream = tokio::net::TcpStream::connect(addr).await?;
|
let stream = tokio::net::TcpStream::connect(addr).await?;
|
||||||
Ok(UsbmuxdConnection::new(Box::new(stream), tag))
|
Ok::<_, IdeviceError>(UsbmuxdConnection::new(Box::new(stream), tag))
|
||||||
});
|
});
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(r) => {
|
Ok(conn) => {
|
||||||
let boxed = Box::new(UsbmuxdConnectionHandle(r));
|
unsafe { *out = Box::into_raw(Box::new(UsbmuxdConnectionHandle(conn))) };
|
||||||
unsafe { *usbmuxd_connection = Box::into_raw(boxed) };
|
std::ptr::null_mut()
|
||||||
null_mut()
|
|
||||||
}
|
}
|
||||||
Err(e) => ffi_err!(e),
|
Err(e) => ffi_err!(e),
|
||||||
}
|
}
|
||||||
@@ -367,20 +373,28 @@ pub unsafe extern "C" fn idevice_usbmuxd_connection_free(
|
|||||||
/// `usbmuxd_Addr` must be a valid, non-null pointer to a location where the handle will be stored
|
/// `usbmuxd_Addr` must be a valid, non-null pointer to a location where the handle will be stored
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub unsafe extern "C" fn idevice_usbmuxd_tcp_addr_new(
|
pub unsafe extern "C" fn idevice_usbmuxd_tcp_addr_new(
|
||||||
addr: *const libc::sockaddr,
|
addr: *const idevice_sockaddr, // <- portable
|
||||||
addr_len: libc::socklen_t,
|
addr_len: idevice_socklen_t,
|
||||||
usbmuxd_addr: *mut *mut UsbmuxdAddrHandle,
|
usbmuxd_addr: *mut *mut UsbmuxdAddrHandle,
|
||||||
) -> *mut IdeviceFfiError {
|
) -> *mut IdeviceFfiError {
|
||||||
let addr = match c_socket_to_rust(addr, addr_len) {
|
if addr.is_null() || usbmuxd_addr.is_null() {
|
||||||
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinterpret as the real platform sockaddr for parsing
|
||||||
|
let addr = addr as *const SockAddr;
|
||||||
|
|
||||||
|
let addr = match c_socket_to_rust(addr, addr_len as _) {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return ffi_err!(e),
|
Err(e) => return ffi_err!(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
let u = UsbmuxdAddr::TcpSocket(addr);
|
let u = UsbmuxdAddr::TcpSocket(addr);
|
||||||
|
|
||||||
let boxed = Box::new(UsbmuxdAddrHandle(u));
|
let boxed = Box::new(UsbmuxdAddrHandle(u));
|
||||||
unsafe { *usbmuxd_addr = Box::into_raw(boxed) };
|
unsafe {
|
||||||
null_mut()
|
*usbmuxd_addr = Box::into_raw(boxed);
|
||||||
|
}
|
||||||
|
std::ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new UsbmuxdAddr struct with a unix socket
|
/// Creates a new UsbmuxdAddr struct with a unix socket
|
||||||
|
|||||||
188
ffi/src/util.rs
188
ffi/src/util.rs
@@ -1,75 +1,185 @@
|
|||||||
// Jackson Coxson
|
// Jackson Coxson
|
||||||
|
|
||||||
use std::{
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||||
ffi::c_int,
|
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
|
||||||
};
|
|
||||||
|
|
||||||
use idevice::IdeviceError;
|
use idevice::IdeviceError;
|
||||||
use libc::{sockaddr_in, sockaddr_in6};
|
|
||||||
|
// portable FFI-facing types (only used in signatures)
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct idevice_sockaddr {
|
||||||
|
_priv: [u8; 0], // opaque; acts as "struct sockaddr" placeholder
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type idevice_socklen_t = libc::socklen_t;
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type idevice_socklen_t = i32;
|
||||||
|
|
||||||
|
// platform sockaddr aliases for implementation
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub(crate) type SockAddr = libc::sockaddr;
|
||||||
|
#[cfg(windows)]
|
||||||
|
use windows_sys::Win32::Networking::WinSock as winsock;
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub(crate) type SockAddr = winsock::SOCKADDR;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use libc::{self, sockaddr_in, sockaddr_in6};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use windows_sys::Win32::Networking::WinSock::{
|
||||||
|
AF_INET, AF_INET6, SOCKADDR_IN as sockaddr_in, SOCKADDR_IN6 as sockaddr_in6,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
type SockLen = libc::socklen_t;
|
||||||
|
#[cfg(windows)]
|
||||||
|
type SockLen = i32; // socklen_t is an int on Windows
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn invalid_arg<T>() -> Result<T, IdeviceError> {
|
||||||
|
Err(IdeviceError::FfiInvalidArg)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn c_socket_to_rust(
|
pub(crate) fn c_socket_to_rust(
|
||||||
addr: *const libc::sockaddr,
|
addr: *const SockAddr,
|
||||||
addr_len: libc::socklen_t,
|
addr_len: SockLen,
|
||||||
) -> Result<SocketAddr, IdeviceError> {
|
) -> Result<SocketAddr, IdeviceError> {
|
||||||
Ok(unsafe {
|
if addr.is_null() {
|
||||||
match (*addr).sa_family as c_int {
|
log::error!("null sockaddr");
|
||||||
|
return invalid_arg();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let family = (*addr).sa_family;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
match family as i32 {
|
||||||
libc::AF_INET => {
|
libc::AF_INET => {
|
||||||
if (addr_len as usize) < std::mem::size_of::<sockaddr_in>() {
|
if (addr_len as usize) < std::mem::size_of::<sockaddr_in>() {
|
||||||
log::error!("Invalid sockaddr_in size");
|
log::error!("Invalid sockaddr_in size");
|
||||||
return Err(IdeviceError::FfiInvalidArg);
|
return invalid_arg();
|
||||||
}
|
}
|
||||||
let addr_in = *(addr as *const sockaddr_in);
|
let a = &*(addr as *const sockaddr_in);
|
||||||
let ip = std::net::Ipv4Addr::from(u32::from_be(addr_in.sin_addr.s_addr));
|
let ip = Ipv4Addr::from(u32::from_be(a.sin_addr.s_addr));
|
||||||
let port = u16::from_be(addr_in.sin_port);
|
let port = u16::from_be(a.sin_port);
|
||||||
std::net::SocketAddr::V4(std::net::SocketAddrV4::new(ip, port))
|
Ok(SocketAddr::V4(std::net::SocketAddrV4::new(ip, port)))
|
||||||
}
|
}
|
||||||
libc::AF_INET6 => {
|
libc::AF_INET6 => {
|
||||||
if addr_len as usize >= std::mem::size_of::<sockaddr_in6>() {
|
if (addr_len as usize) < std::mem::size_of::<sockaddr_in6>() {
|
||||||
let addr_in6 = *(addr as *const sockaddr_in6);
|
log::error!("Invalid sockaddr_in6 size");
|
||||||
let ip = std::net::Ipv6Addr::from(addr_in6.sin6_addr.s6_addr);
|
return invalid_arg();
|
||||||
let port = u16::from_be(addr_in6.sin6_port);
|
}
|
||||||
std::net::SocketAddr::V6(std::net::SocketAddrV6::new(
|
let a = &*(addr as *const sockaddr_in6);
|
||||||
|
let ip = Ipv6Addr::from(a.sin6_addr.s6_addr);
|
||||||
|
let port = u16::from_be(a.sin6_port);
|
||||||
|
Ok(SocketAddr::V6(std::net::SocketAddrV6::new(
|
||||||
ip,
|
ip,
|
||||||
port,
|
port,
|
||||||
addr_in6.sin6_flowinfo,
|
a.sin6_flowinfo,
|
||||||
addr_in6.sin6_scope_id,
|
a.sin6_scope_id,
|
||||||
))
|
)))
|
||||||
} else {
|
|
||||||
log::error!("Invalid sockaddr_in6 size");
|
|
||||||
return Err(IdeviceError::FfiInvalidArg);
|
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
log::error!(
|
||||||
|
"Unsupported socket address family: {}",
|
||||||
|
(*addr).sa_family as i32
|
||||||
|
);
|
||||||
|
invalid_arg()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
match family {
|
||||||
|
AF_INET => {
|
||||||
|
if (addr_len as usize) < std::mem::size_of::<sockaddr_in>() {
|
||||||
|
log::error!("Invalid SOCKADDR_IN size");
|
||||||
|
return invalid_arg();
|
||||||
|
}
|
||||||
|
let a = &*(addr as *const sockaddr_in);
|
||||||
|
// IN_ADDR is a union; use S_un.S_addr (network byte order)
|
||||||
|
let ip_be = a.sin_addr.S_un.S_addr;
|
||||||
|
let ip = Ipv4Addr::from(u32::from_be(ip_be));
|
||||||
|
let port = u16::from_be(a.sin_port);
|
||||||
|
Ok(SocketAddr::V4(std::net::SocketAddrV4::new(ip, port)))
|
||||||
|
}
|
||||||
|
AF_INET6 => {
|
||||||
|
if (addr_len as usize) < std::mem::size_of::<sockaddr_in6>() {
|
||||||
|
log::error!("Invalid SOCKADDR_IN6 size");
|
||||||
|
return invalid_arg();
|
||||||
|
}
|
||||||
|
let a = &*(addr as *const sockaddr_in6);
|
||||||
|
// IN6_ADDR is a union; read the 16 Byte array
|
||||||
|
let bytes: [u8; 16] = a.sin6_addr.u.Byte;
|
||||||
|
let ip = Ipv6Addr::from(bytes);
|
||||||
|
let port = u16::from_be(a.sin6_port);
|
||||||
|
let scope_id = a.Anonymous.sin6_scope_id;
|
||||||
|
Ok(SocketAddr::V6(std::net::SocketAddrV6::new(
|
||||||
|
ip,
|
||||||
|
port,
|
||||||
|
a.sin6_flowinfo,
|
||||||
|
scope_id,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("Unsupported socket address family: {}", (*addr).sa_family);
|
log::error!("Unsupported socket address family: {}", (*addr).sa_family);
|
||||||
return Err(IdeviceError::FfiInvalidArg);
|
invalid_arg()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn c_addr_to_rust(addr: *const libc::sockaddr) -> Result<IpAddr, IdeviceError> {
|
pub(crate) fn c_addr_to_rust(addr: *const SockAddr) -> Result<IpAddr, IdeviceError> {
|
||||||
|
if addr.is_null() {
|
||||||
|
log::error!("null sockaddr");
|
||||||
|
return invalid_arg();
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// Check the address family
|
#[cfg(unix)]
|
||||||
match (*addr).sa_family as c_int {
|
let family = (*addr).sa_family as i32;
|
||||||
|
#[cfg(windows)]
|
||||||
|
let family = (*addr).sa_family;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
match family {
|
||||||
libc::AF_INET => {
|
libc::AF_INET => {
|
||||||
// Convert sockaddr_in (IPv4) to IpAddr
|
let a = &*(addr as *const sockaddr_in);
|
||||||
let sockaddr_in = addr as *const sockaddr_in;
|
let octets = u32::from_be(a.sin_addr.s_addr).to_be_bytes();
|
||||||
let ip = (*sockaddr_in).sin_addr.s_addr;
|
|
||||||
let octets = u32::from_be(ip).to_be_bytes();
|
|
||||||
Ok(IpAddr::V4(Ipv4Addr::new(
|
Ok(IpAddr::V4(Ipv4Addr::new(
|
||||||
octets[0], octets[1], octets[2], octets[3],
|
octets[0], octets[1], octets[2], octets[3],
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
libc::AF_INET6 => {
|
libc::AF_INET6 => {
|
||||||
// Convert sockaddr_in6 (IPv6) to IpAddr
|
let a = &*(addr as *const sockaddr_in6);
|
||||||
let sockaddr_in6 = addr as *const sockaddr_in6;
|
Ok(IpAddr::V6(Ipv6Addr::from(a.sin6_addr.s6_addr)))
|
||||||
let ip = (*sockaddr_in6).sin6_addr.s6_addr;
|
}
|
||||||
Ok(IpAddr::V6(Ipv6Addr::from(ip)))
|
_ => {
|
||||||
|
log::error!(
|
||||||
|
"Unsupported socket address family: {}",
|
||||||
|
(*addr).sa_family as i32
|
||||||
|
);
|
||||||
|
invalid_arg()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
match family {
|
||||||
|
AF_INET => {
|
||||||
|
let a = &*(addr as *const sockaddr_in);
|
||||||
|
let ip_be = a.sin_addr.S_un.S_addr;
|
||||||
|
Ok(IpAddr::V4(Ipv4Addr::from(u32::from_be(ip_be))))
|
||||||
|
}
|
||||||
|
AF_INET6 => {
|
||||||
|
let a = &*(addr as *const sockaddr_in6);
|
||||||
|
let bytes: [u8; 16] = a.sin6_addr.u.Byte;
|
||||||
|
Ok(IpAddr::V6(Ipv6Addr::from(bytes)))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("Unsupported socket address family: {}", (*addr).sa_family);
|
log::error!("Unsupported socket address family: {}", (*addr).sa_family);
|
||||||
Err(IdeviceError::FfiInvalidArg)
|
invalid_arg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user