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