1use std::os::unix::io::{AsRawFd, RawFd};
4use std::{mem, ptr};
5
6use glib::{prelude::*, translate::*};
7
8use crate::{ffi, FDMessage};
9
10pub trait FDMessageExtManual: IsA<FDMessage> + Sized {
11 #[doc(alias = "g_unix_fd_message_append_fd")]
26 fn append_fd<T: AsRawFd>(&self, fd: T) -> Result<(), glib::Error> {
27 unsafe {
28 let mut error = ptr::null_mut();
29 ffi::g_unix_fd_message_append_fd(
30 self.as_ref().to_glib_none().0,
31 fd.as_raw_fd(),
32 &mut error,
33 );
34 if error.is_null() {
35 Ok(())
36 } else {
37 Err(from_glib_full(error))
38 }
39 }
40 }
41 #[doc(alias = "g_unix_fd_message_steal_fds")]
64 fn steal_fds(&self) -> Vec<RawFd> {
65 unsafe {
66 let mut length = mem::MaybeUninit::uninit();
67 let ret = FromGlibContainer::from_glib_full_num(
68 ffi::g_unix_fd_message_steal_fds(
69 self.as_ref().to_glib_none().0,
70 length.as_mut_ptr(),
71 ),
72 length.assume_init() as usize,
73 );
74 ret
75 }
76 }
77}
78
79impl<O: IsA<FDMessage>> FDMessageExtManual for O {}
80
81#[cfg(test)]
82mod tests {
83 use std::{
84 io,
85 os::unix::io::{AsRawFd, FromRawFd, OwnedFd},
86 };
87
88 use crate::prelude::*;
89 use gio::prelude::UnixFDListExt;
90 use gio::Cancellable;
91 use gio::Socket;
92 use glib::prelude::Cast;
93
94 #[test]
95 fn socket_messages() {
96 let mut fds = [0 as libc::c_int; 2];
97 let (out_sock, in_sock) = unsafe {
98 let ret = libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr());
99 if ret != 0 {
100 panic!("{}", io::Error::last_os_error());
101 }
102 (
103 Socket::from_fd(OwnedFd::from_raw_fd(fds[0])).unwrap(),
104 Socket::from_fd(OwnedFd::from_raw_fd(fds[1])).unwrap(),
105 )
106 };
107
108 let fd_msg = crate::FDMessage::new();
109 fd_msg.append_fd(out_sock.as_raw_fd()).unwrap();
110 let vs = [gio::OutputVector::new(&[0])];
111 let ctrl_msgs = [fd_msg.upcast()];
112 let mut out_msg = [gio::OutputMessage::new(
113 gio::SocketAddress::NONE,
114 vs.as_slice(),
115 ctrl_msgs.as_slice(),
116 )];
117 let written = gio::prelude::SocketExtManual::send_messages(
118 &out_sock,
119 out_msg.as_mut_slice(),
120 0,
121 Cancellable::NONE,
122 )
123 .unwrap();
124 assert_eq!(written, 1);
125 assert_eq!(out_msg[0].bytes_sent(), 1);
126
127 let mut v = [0u8];
128 let mut vs = [gio::InputVector::new(v.as_mut_slice())];
129 let mut ctrl_msgs = gio::SocketControlMessages::new();
130 let mut in_msg = [gio::InputMessage::new(
131 None,
132 vs.as_mut_slice(),
133 Some(&mut ctrl_msgs),
134 )];
135 let received = gio::prelude::SocketExtManual::receive_messages(
136 &in_sock,
137 in_msg.as_mut_slice(),
138 0,
139 Cancellable::NONE,
140 )
141 .unwrap();
142
143 assert_eq!(received, 1);
144 assert_eq!(in_msg[0].bytes_received(), 1);
145 assert_eq!(ctrl_msgs.len(), 1);
146 let fds = ctrl_msgs[0]
147 .downcast_ref::<crate::FDMessage>()
148 .unwrap()
149 .fd_list();
150 assert_eq!(fds.length(), 1);
151 }
152}