1use std::os::unix::io::{AsRawFd, RawFd};
4use std::{mem, ptr};
5
6use glib::{prelude::*, translate::*};
7
8use crate::{FDMessage, ffi};
9
10pub trait FDMessageExtManual: IsA<FDMessage> + Sized {
11 #[doc(alias = "g_unix_fd_message_append_fd")]
12 fn append_fd<T: AsRawFd>(&self, fd: T) -> Result<(), glib::Error> {
13 unsafe {
14 let mut error = ptr::null_mut();
15 ffi::g_unix_fd_message_append_fd(
16 self.as_ref().to_glib_none().0,
17 fd.as_raw_fd(),
18 &mut error,
19 );
20 if error.is_null() {
21 Ok(())
22 } else {
23 Err(from_glib_full(error))
24 }
25 }
26 }
27 #[doc(alias = "g_unix_fd_message_steal_fds")]
28 fn steal_fds(&self) -> Vec<RawFd> {
29 unsafe {
30 let mut length = mem::MaybeUninit::uninit();
31
32 FromGlibContainer::from_glib_full_num(
33 ffi::g_unix_fd_message_steal_fds(
34 self.as_ref().to_glib_none().0,
35 length.as_mut_ptr(),
36 ),
37 length.assume_init() as usize,
38 )
39 }
40 }
41}
42
43impl<O: IsA<FDMessage>> FDMessageExtManual for O {}
44
45#[cfg(test)]
46mod tests {
47 use std::{
48 io,
49 os::unix::io::{AsRawFd, FromRawFd, OwnedFd},
50 };
51
52 use crate::prelude::*;
53 use gio::Cancellable;
54 use gio::Socket;
55 use gio::prelude::UnixFDListExt;
56 use glib::prelude::Cast;
57
58 #[test]
59 fn socket_messages() {
60 let mut fds = [0 as libc::c_int; 2];
61 let (out_sock, in_sock) = unsafe {
62 let ret = libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr());
63 if ret != 0 {
64 panic!("{}", io::Error::last_os_error());
65 }
66 (
67 Socket::from_fd(OwnedFd::from_raw_fd(fds[0])).unwrap(),
68 Socket::from_fd(OwnedFd::from_raw_fd(fds[1])).unwrap(),
69 )
70 };
71
72 let fd_msg = crate::FDMessage::new();
73 fd_msg.append_fd(out_sock.as_raw_fd()).unwrap();
74 let vs = [gio::OutputVector::new(&[0])];
75 let ctrl_msgs = [fd_msg.upcast()];
76 let mut out_msg = [gio::OutputMessage::new(
77 gio::SocketAddress::NONE,
78 vs.as_slice(),
79 ctrl_msgs.as_slice(),
80 )];
81 let written = gio::prelude::SocketExtManual::send_messages(
82 &out_sock,
83 out_msg.as_mut_slice(),
84 0,
85 Cancellable::NONE,
86 )
87 .unwrap();
88 assert_eq!(written, 1);
89 assert_eq!(out_msg[0].bytes_sent(), 1);
90
91 let mut v = [0u8];
92 let mut vs = [gio::InputVector::new(v.as_mut_slice())];
93 let mut ctrl_msgs = gio::SocketControlMessages::new();
94 let mut in_msg = [gio::InputMessage::new(
95 None,
96 vs.as_mut_slice(),
97 Some(&mut ctrl_msgs),
98 )];
99 let received = gio::prelude::SocketExtManual::receive_messages(
100 &in_sock,
101 in_msg.as_mut_slice(),
102 0,
103 Cancellable::NONE,
104 )
105 .unwrap();
106
107 assert_eq!(received, 1);
108 assert_eq!(in_msg[0].bytes_received(), 1);
109 assert_eq!(ctrl_msgs.len(), 1);
110 let fds = ctrl_msgs[0]
111 .downcast_ref::<crate::FDMessage>()
112 .unwrap()
113 .fd_list();
114 assert_eq!(fds.length(), 1);
115 }
116}