1use crate::{
6 ffi, AsyncResult, Cancellable, Socket, SocketAddress, SocketConnection, SocketListenerEvent,
7 SocketProtocol, SocketType,
8};
9use glib::{
10 object::ObjectType as _,
11 prelude::*,
12 signal::{connect_raw, SignalHandlerId},
13 translate::*,
14};
15use std::{boxed::Box as Box_, pin::Pin};
16
17glib::wrapper! {
18 #[doc(alias = "GSocketListener")]
19 pub struct SocketListener(Object<ffi::GSocketListener, ffi::GSocketListenerClass>);
20
21 match fn {
22 type_ => || ffi::g_socket_listener_get_type(),
23 }
24}
25
26impl SocketListener {
27 pub const NONE: Option<&'static SocketListener> = None;
28
29 #[doc(alias = "g_socket_listener_new")]
30 pub fn new() -> SocketListener {
31 unsafe { from_glib_full(ffi::g_socket_listener_new()) }
32 }
33}
34
35impl Default for SocketListener {
36 fn default() -> Self {
37 Self::new()
38 }
39}
40
41pub trait SocketListenerExt: IsA<SocketListener> + 'static {
42 #[doc(alias = "g_socket_listener_accept")]
43 fn accept(
44 &self,
45 cancellable: Option<&impl IsA<Cancellable>>,
46 ) -> Result<(SocketConnection, Option<glib::Object>), glib::Error> {
47 unsafe {
48 let mut source_object = std::ptr::null_mut();
49 let mut error = std::ptr::null_mut();
50 let ret = ffi::g_socket_listener_accept(
51 self.as_ref().to_glib_none().0,
52 &mut source_object,
53 cancellable.map(|p| p.as_ref()).to_glib_none().0,
54 &mut error,
55 );
56 if error.is_null() {
57 Ok((from_glib_full(ret), from_glib_none(source_object)))
58 } else {
59 Err(from_glib_full(error))
60 }
61 }
62 }
63
64 #[doc(alias = "g_socket_listener_accept_async")]
65 fn accept_async<
66 P: FnOnce(Result<(SocketConnection, Option<glib::Object>), glib::Error>) + 'static,
67 >(
68 &self,
69 cancellable: Option<&impl IsA<Cancellable>>,
70 callback: P,
71 ) {
72 let main_context = glib::MainContext::ref_thread_default();
73 let is_main_context_owner = main_context.is_owner();
74 let has_acquired_main_context = (!is_main_context_owner)
75 .then(|| main_context.acquire().ok())
76 .flatten();
77 assert!(
78 is_main_context_owner || has_acquired_main_context.is_some(),
79 "Async operations only allowed if the thread is owning the MainContext"
80 );
81
82 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
83 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
84 unsafe extern "C" fn accept_async_trampoline<
85 P: FnOnce(Result<(SocketConnection, Option<glib::Object>), glib::Error>) + 'static,
86 >(
87 _source_object: *mut glib::gobject_ffi::GObject,
88 res: *mut crate::ffi::GAsyncResult,
89 user_data: glib::ffi::gpointer,
90 ) {
91 let mut error = std::ptr::null_mut();
92 let mut source_object = std::ptr::null_mut();
93 let ret = ffi::g_socket_listener_accept_finish(
94 _source_object as *mut _,
95 res,
96 &mut source_object,
97 &mut error,
98 );
99 let result = if error.is_null() {
100 Ok((from_glib_full(ret), from_glib_none(source_object)))
101 } else {
102 Err(from_glib_full(error))
103 };
104 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
105 Box_::from_raw(user_data as *mut _);
106 let callback: P = callback.into_inner();
107 callback(result);
108 }
109 let callback = accept_async_trampoline::<P>;
110 unsafe {
111 ffi::g_socket_listener_accept_async(
112 self.as_ref().to_glib_none().0,
113 cancellable.map(|p| p.as_ref()).to_glib_none().0,
114 Some(callback),
115 Box_::into_raw(user_data) as *mut _,
116 );
117 }
118 }
119
120 fn accept_future(
121 &self,
122 ) -> Pin<
123 Box_<
124 dyn std::future::Future<
125 Output = Result<(SocketConnection, Option<glib::Object>), glib::Error>,
126 > + 'static,
127 >,
128 > {
129 Box_::pin(crate::GioFuture::new(
130 self,
131 move |obj, cancellable, send| {
132 obj.accept_async(Some(cancellable), move |res| {
133 send.resolve(res);
134 });
135 },
136 ))
137 }
138
139 #[doc(alias = "g_socket_listener_accept_socket")]
140 fn accept_socket(
141 &self,
142 cancellable: Option<&impl IsA<Cancellable>>,
143 ) -> Result<(Socket, Option<glib::Object>), glib::Error> {
144 unsafe {
145 let mut source_object = std::ptr::null_mut();
146 let mut error = std::ptr::null_mut();
147 let ret = ffi::g_socket_listener_accept_socket(
148 self.as_ref().to_glib_none().0,
149 &mut source_object,
150 cancellable.map(|p| p.as_ref()).to_glib_none().0,
151 &mut error,
152 );
153 if error.is_null() {
154 Ok((from_glib_full(ret), from_glib_none(source_object)))
155 } else {
156 Err(from_glib_full(error))
157 }
158 }
159 }
160
161 #[doc(alias = "g_socket_listener_accept_socket_async")]
162 fn accept_socket_async<
163 P: FnOnce(Result<(Socket, Option<glib::Object>), glib::Error>) + 'static,
164 >(
165 &self,
166 cancellable: Option<&impl IsA<Cancellable>>,
167 callback: P,
168 ) {
169 let main_context = glib::MainContext::ref_thread_default();
170 let is_main_context_owner = main_context.is_owner();
171 let has_acquired_main_context = (!is_main_context_owner)
172 .then(|| main_context.acquire().ok())
173 .flatten();
174 assert!(
175 is_main_context_owner || has_acquired_main_context.is_some(),
176 "Async operations only allowed if the thread is owning the MainContext"
177 );
178
179 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
180 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
181 unsafe extern "C" fn accept_socket_async_trampoline<
182 P: FnOnce(Result<(Socket, Option<glib::Object>), glib::Error>) + 'static,
183 >(
184 _source_object: *mut glib::gobject_ffi::GObject,
185 res: *mut crate::ffi::GAsyncResult,
186 user_data: glib::ffi::gpointer,
187 ) {
188 let mut error = std::ptr::null_mut();
189 let mut source_object = std::ptr::null_mut();
190 let ret = ffi::g_socket_listener_accept_socket_finish(
191 _source_object as *mut _,
192 res,
193 &mut source_object,
194 &mut error,
195 );
196 let result = if error.is_null() {
197 Ok((from_glib_full(ret), from_glib_none(source_object)))
198 } else {
199 Err(from_glib_full(error))
200 };
201 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
202 Box_::from_raw(user_data as *mut _);
203 let callback: P = callback.into_inner();
204 callback(result);
205 }
206 let callback = accept_socket_async_trampoline::<P>;
207 unsafe {
208 ffi::g_socket_listener_accept_socket_async(
209 self.as_ref().to_glib_none().0,
210 cancellable.map(|p| p.as_ref()).to_glib_none().0,
211 Some(callback),
212 Box_::into_raw(user_data) as *mut _,
213 );
214 }
215 }
216
217 fn accept_socket_future(
218 &self,
219 ) -> Pin<
220 Box_<
221 dyn std::future::Future<Output = Result<(Socket, Option<glib::Object>), glib::Error>>
222 + 'static,
223 >,
224 > {
225 Box_::pin(crate::GioFuture::new(
226 self,
227 move |obj, cancellable, send| {
228 obj.accept_socket_async(Some(cancellable), move |res| {
229 send.resolve(res);
230 });
231 },
232 ))
233 }
234
235 #[doc(alias = "g_socket_listener_add_address")]
236 fn add_address(
237 &self,
238 address: &impl IsA<SocketAddress>,
239 type_: SocketType,
240 protocol: SocketProtocol,
241 source_object: Option<&impl IsA<glib::Object>>,
242 ) -> Result<SocketAddress, glib::Error> {
243 unsafe {
244 let mut effective_address = std::ptr::null_mut();
245 let mut error = std::ptr::null_mut();
246 let is_ok = ffi::g_socket_listener_add_address(
247 self.as_ref().to_glib_none().0,
248 address.as_ref().to_glib_none().0,
249 type_.into_glib(),
250 protocol.into_glib(),
251 source_object.map(|p| p.as_ref()).to_glib_none().0,
252 &mut effective_address,
253 &mut error,
254 );
255 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
256 if error.is_null() {
257 Ok(from_glib_full(effective_address))
258 } else {
259 Err(from_glib_full(error))
260 }
261 }
262 }
263
264 #[doc(alias = "g_socket_listener_add_any_inet_port")]
265 fn add_any_inet_port(
266 &self,
267 source_object: Option<&impl IsA<glib::Object>>,
268 ) -> Result<u16, glib::Error> {
269 unsafe {
270 let mut error = std::ptr::null_mut();
271 let ret = ffi::g_socket_listener_add_any_inet_port(
272 self.as_ref().to_glib_none().0,
273 source_object.map(|p| p.as_ref()).to_glib_none().0,
274 &mut error,
275 );
276 if error.is_null() {
277 Ok(ret)
278 } else {
279 Err(from_glib_full(error))
280 }
281 }
282 }
283
284 #[doc(alias = "g_socket_listener_add_inet_port")]
285 fn add_inet_port(
286 &self,
287 port: u16,
288 source_object: Option<&impl IsA<glib::Object>>,
289 ) -> Result<(), glib::Error> {
290 unsafe {
291 let mut error = std::ptr::null_mut();
292 let is_ok = ffi::g_socket_listener_add_inet_port(
293 self.as_ref().to_glib_none().0,
294 port,
295 source_object.map(|p| p.as_ref()).to_glib_none().0,
296 &mut error,
297 );
298 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
299 if error.is_null() {
300 Ok(())
301 } else {
302 Err(from_glib_full(error))
303 }
304 }
305 }
306
307 #[doc(alias = "g_socket_listener_add_socket")]
308 fn add_socket(
309 &self,
310 socket: &impl IsA<Socket>,
311 source_object: Option<&impl IsA<glib::Object>>,
312 ) -> Result<(), glib::Error> {
313 unsafe {
314 let mut error = std::ptr::null_mut();
315 let is_ok = ffi::g_socket_listener_add_socket(
316 self.as_ref().to_glib_none().0,
317 socket.as_ref().to_glib_none().0,
318 source_object.map(|p| p.as_ref()).to_glib_none().0,
319 &mut error,
320 );
321 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
322 if error.is_null() {
323 Ok(())
324 } else {
325 Err(from_glib_full(error))
326 }
327 }
328 }
329
330 #[doc(alias = "g_socket_listener_close")]
331 fn close(&self) {
332 unsafe {
333 ffi::g_socket_listener_close(self.as_ref().to_glib_none().0);
334 }
335 }
336
337 #[doc(alias = "g_socket_listener_set_backlog")]
338 fn set_backlog(&self, listen_backlog: i32) {
339 unsafe {
340 ffi::g_socket_listener_set_backlog(self.as_ref().to_glib_none().0, listen_backlog);
341 }
342 }
343
344 #[doc(alias = "listen-backlog")]
345 fn listen_backlog(&self) -> i32 {
346 ObjectExt::property(self.as_ref(), "listen-backlog")
347 }
348
349 #[doc(alias = "listen-backlog")]
350 fn set_listen_backlog(&self, listen_backlog: i32) {
351 ObjectExt::set_property(self.as_ref(), "listen-backlog", listen_backlog)
352 }
353
354 #[doc(alias = "event")]
355 fn connect_event<F: Fn(&Self, SocketListenerEvent, &Socket) + 'static>(
356 &self,
357 f: F,
358 ) -> SignalHandlerId {
359 unsafe extern "C" fn event_trampoline<
360 P: IsA<SocketListener>,
361 F: Fn(&P, SocketListenerEvent, &Socket) + 'static,
362 >(
363 this: *mut ffi::GSocketListener,
364 event: ffi::GSocketListenerEvent,
365 socket: *mut ffi::GSocket,
366 f: glib::ffi::gpointer,
367 ) {
368 let f: &F = &*(f as *const F);
369 f(
370 SocketListener::from_glib_borrow(this).unsafe_cast_ref(),
371 from_glib(event),
372 &from_glib_borrow(socket),
373 )
374 }
375 unsafe {
376 let f: Box_<F> = Box_::new(f);
377 connect_raw(
378 self.as_ptr() as *mut _,
379 c"event".as_ptr() as *const _,
380 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
381 event_trampoline::<Self, F> as *const (),
382 )),
383 Box_::into_raw(f),
384 )
385 }
386 }
387
388 #[doc(alias = "listen-backlog")]
389 fn connect_listen_backlog_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
390 unsafe extern "C" fn notify_listen_backlog_trampoline<
391 P: IsA<SocketListener>,
392 F: Fn(&P) + 'static,
393 >(
394 this: *mut ffi::GSocketListener,
395 _param_spec: glib::ffi::gpointer,
396 f: glib::ffi::gpointer,
397 ) {
398 let f: &F = &*(f as *const F);
399 f(SocketListener::from_glib_borrow(this).unsafe_cast_ref())
400 }
401 unsafe {
402 let f: Box_<F> = Box_::new(f);
403 connect_raw(
404 self.as_ptr() as *mut _,
405 c"notify::listen-backlog".as_ptr() as *const _,
406 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
407 notify_listen_backlog_trampoline::<Self, F> as *const (),
408 )),
409 Box_::into_raw(f),
410 )
411 }
412 }
413}
414
415impl<O: IsA<SocketListener>> SocketListenerExt for O {}