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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
// Take a look at the license at the top of the repository in the LICENSE file.
#[cfg(not(feature = "dox"))]
use std::ffi::OsStr;
#[cfg(unix)]
#[cfg(not(feature = "dox"))]
use std::os::unix::ffi::OsStrExt;
use std::{path, ptr, slice};
use glib::translate::*;
use crate::{prelude::*, SocketAddress, UnixSocketAddress, UnixSocketAddressType};
#[derive(Debug)]
pub enum UnixSocketAddressPath<'a> {
Path(&'a path::Path),
Anonymous,
Abstract(&'a [u8]),
AbstractPadded(&'a [u8]),
}
impl<'a> UnixSocketAddressPath<'a> {
fn to_type(&self) -> UnixSocketAddressType {
use self::UnixSocketAddressPath::*;
match *self {
Path(_) => UnixSocketAddressType::Path,
Anonymous => UnixSocketAddressType::Anonymous,
Abstract(_) => UnixSocketAddressType::Abstract,
AbstractPadded(_) => UnixSocketAddressType::AbstractPadded,
}
}
}
impl UnixSocketAddress {
/// Creates a new [`UnixSocketAddress`][crate::UnixSocketAddress] for `path`.
///
/// To create abstract socket addresses, on systems that support that,
/// use `g_unix_socket_address_new_abstract()`.
/// ## `path`
/// the socket path
///
/// # Returns
///
/// a new [`UnixSocketAddress`][crate::UnixSocketAddress]
#[doc(alias = "g_unix_socket_address_new")]
pub fn new(path: &path::Path) -> UnixSocketAddress {
unsafe {
SocketAddress::from_glib_full(ffi::g_unix_socket_address_new(path.to_glib_none().0))
.unsafe_cast()
}
}
/// Creates a new [`UnixSocketAddress`][crate::UnixSocketAddress] of type `type_` with name `path`.
///
/// If `type_` is [`UnixSocketAddressType::Path`][crate::UnixSocketAddressType::Path], this is equivalent to
/// calling [`new()`][Self::new()].
///
/// If `type_` is [`UnixSocketAddressType::Anonymous`][crate::UnixSocketAddressType::Anonymous], `path` and `path_len` will be
/// ignored.
///
/// If `path_type` is [`UnixSocketAddressType::Abstract`][crate::UnixSocketAddressType::Abstract], then `path_len`
/// bytes of `path` will be copied to the socket's path, and only those
/// bytes will be considered part of the name. (If `path_len` is -1,
/// then `path` is assumed to be NUL-terminated.) For example, if `path`
/// was "test", then calling [`SocketAddressExt::native_size()`][crate::prelude::SocketAddressExt::native_size()] on the
/// returned socket would return 7 (2 bytes of overhead, 1 byte for the
/// abstract-socket indicator byte, and 4 bytes for the name "test").
///
/// If `path_type` is [`UnixSocketAddressType::AbstractPadded`][crate::UnixSocketAddressType::AbstractPadded], then
/// `path_len` bytes of `path` will be copied to the socket's path, the
/// rest of the path will be padded with 0 bytes, and the entire
/// zero-padded buffer will be considered the name. (As above, if
/// `path_len` is -1, then `path` is assumed to be NUL-terminated.) In
/// this case, [`SocketAddressExt::native_size()`][crate::prelude::SocketAddressExt::native_size()] will always return
/// the full size of a `struct sockaddr_un`, although
/// [`UnixSocketAddressExt::path_len()`][crate::prelude::UnixSocketAddressExt::path_len()] will still return just the
/// length of `path`.
///
/// [`UnixSocketAddressType::Abstract`][crate::UnixSocketAddressType::Abstract] is preferred over
/// [`UnixSocketAddressType::AbstractPadded`][crate::UnixSocketAddressType::AbstractPadded] for new programs. Of course,
/// when connecting to a server created by another process, you must
/// use the appropriate type corresponding to how that process created
/// its listening socket.
/// ## `path`
/// the name
/// ## `type_`
/// a [`UnixSocketAddressType`][crate::UnixSocketAddressType]
///
/// # Returns
///
/// a new [`UnixSocketAddress`][crate::UnixSocketAddress]
#[doc(alias = "g_unix_socket_address_new_with_type")]
pub fn with_type(address_type: UnixSocketAddressPath) -> Self {
use self::UnixSocketAddressPath::*;
let type_ = address_type.to_type();
let (path, len) = match address_type {
Path(path) => (path.to_glib_none().0, path.as_os_str().len()),
Abstract(path) | AbstractPadded(path) => {
(path.to_glib_none().0 as *mut libc::c_char, path.len())
}
Anonymous => (ptr::null_mut(), 0),
};
unsafe {
SocketAddress::from_glib_full(ffi::g_unix_socket_address_new_with_type(
path,
len as i32,
type_.into_glib(),
))
.unsafe_cast()
}
}
}
pub trait UnixSocketAddressExtManual {
/// Gets `self`'s path, or for abstract sockets the "name".
///
/// Guaranteed to be zero-terminated, but an abstract socket
/// may contain embedded zeros, and thus you should use
/// [`UnixSocketAddressExt::path_len()`][crate::prelude::UnixSocketAddressExt::path_len()] to get the true length
/// of this string.
///
/// # Returns
///
/// the path for `self`
#[doc(alias = "g_unix_socket_address_get_path")]
#[doc(alias = "get_path")]
fn path(&self) -> Option<UnixSocketAddressPath>;
}
impl<O: IsA<UnixSocketAddress>> UnixSocketAddressExtManual for O {
fn path(&self) -> Option<UnixSocketAddressPath> {
use self::UnixSocketAddressPath::*;
let path = unsafe {
let path = ffi::g_unix_socket_address_get_path(self.as_ref().to_glib_none().0);
if path.is_null() || self.path_len() == 0 {
&[]
} else {
slice::from_raw_parts(path as *const u8, self.path_len())
}
};
match self.address_type() {
UnixSocketAddressType::Anonymous => Some(Anonymous),
#[cfg(not(feature = "dox"))]
UnixSocketAddressType::Path => Some(Path(path::Path::new(OsStr::from_bytes(path)))),
#[cfg(feature = "dox")]
UnixSocketAddressType::Path => unreachable!(),
UnixSocketAddressType::Abstract => Some(Abstract(path)),
UnixSocketAddressType::AbstractPadded => Some(AbstractPadded(path)),
UnixSocketAddressType::Invalid | UnixSocketAddressType::__Unknown(_) => None,
}
}
}