1 // Take a look at the license at the top of the repository in the LICENSE file. 2 3 use crate::Cancellable; 4 use crate::Socket; 5 use crate::SocketAddress; 6 use glib::object::{Cast, IsA}; 7 use glib::translate::*; 8 use std::cell::RefCell; 9 use std::mem::transmute; 10 #[cfg(all(not(unix), feature = "dox"))] 11 use std::os::raw::c_int; 12 #[cfg(all(not(windows), feature = "dox"))] 13 use std::os::raw::c_void; 14 use std::pin::Pin; 15 use std::ptr; 16 17 use futures_core::stream::Stream; 18 19 #[cfg(unix)] 20 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 21 22 #[cfg(windows)] 23 use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; 24 25 impl Socket { 26 #[cfg(any(unix, feature = "dox"))] from_fd<T: IntoRawFd>(fd: T) -> Result<Socket, glib::Error>27 pub unsafe fn from_fd<T: IntoRawFd>(fd: T) -> Result<Socket, glib::Error> { 28 let fd = fd.into_raw_fd(); 29 let mut error = ptr::null_mut(); 30 let ret = ffi::g_socket_new_from_fd(fd, &mut error); 31 if error.is_null() { 32 Ok(from_glib_full(ret)) 33 } else { 34 Err(from_glib_full(error)) 35 } 36 } 37 #[cfg(any(windows, feature = "dox"))] from_socket<T: IntoRawSocket>(socket: T) -> Result<Socket, glib::Error>38 pub unsafe fn from_socket<T: IntoRawSocket>(socket: T) -> Result<Socket, glib::Error> { 39 let socket = socket.into_raw_socket(); 40 let mut error = ptr::null_mut(); 41 let ret = ffi::g_socket_new_from_fd(socket as i32, &mut error); 42 if error.is_null() { 43 Ok(from_glib_full(ret)) 44 } else { 45 Err(from_glib_full(error)) 46 } 47 } 48 } 49 50 #[cfg(any(unix, feature = "dox"))] 51 impl AsRawFd for Socket { as_raw_fd(&self) -> RawFd52 fn as_raw_fd(&self) -> RawFd { 53 unsafe { ffi::g_socket_get_fd(self.to_glib_none().0) as _ } 54 } 55 } 56 57 #[cfg(any(windows, feature = "dox"))] 58 impl AsRawSocket for Socket { as_raw_socket(&self) -> RawSocket59 fn as_raw_socket(&self) -> RawSocket { 60 unsafe { ffi::g_socket_get_fd(self.to_glib_none().0) as _ } 61 } 62 } 63 64 pub trait SocketExtManual: Sized { 65 #[doc(alias = "g_socket_receive")] receive<B: AsMut<[u8]>, C: IsA<Cancellable>>( &self, buffer: B, cancellable: Option<&C>, ) -> Result<usize, glib::Error>66 fn receive<B: AsMut<[u8]>, C: IsA<Cancellable>>( 67 &self, 68 buffer: B, 69 cancellable: Option<&C>, 70 ) -> Result<usize, glib::Error>; 71 #[doc(alias = "g_socket_receive_from")] receive_from<B: AsMut<[u8]>, C: IsA<Cancellable>>( &self, buffer: B, cancellable: Option<&C>, ) -> Result<(usize, SocketAddress), glib::Error>72 fn receive_from<B: AsMut<[u8]>, C: IsA<Cancellable>>( 73 &self, 74 buffer: B, 75 cancellable: Option<&C>, 76 ) -> Result<(usize, SocketAddress), glib::Error>; 77 #[doc(alias = "g_socket_receive_with_blocking")] receive_with_blocking<B: AsMut<[u8]>, C: IsA<Cancellable>>( &self, buffer: B, blocking: bool, cancellable: Option<&C>, ) -> Result<usize, glib::Error>78 fn receive_with_blocking<B: AsMut<[u8]>, C: IsA<Cancellable>>( 79 &self, 80 buffer: B, 81 blocking: bool, 82 cancellable: Option<&C>, 83 ) -> Result<usize, glib::Error>; 84 85 #[doc(alias = "g_socket_send")] send<B: AsRef<[u8]>, C: IsA<Cancellable>>( &self, buffer: B, cancellable: Option<&C>, ) -> Result<usize, glib::Error>86 fn send<B: AsRef<[u8]>, C: IsA<Cancellable>>( 87 &self, 88 buffer: B, 89 cancellable: Option<&C>, 90 ) -> Result<usize, glib::Error>; 91 #[doc(alias = "g_socket_send_to")] send_to<B: AsRef<[u8]>, P: IsA<SocketAddress>, C: IsA<Cancellable>>( &self, address: Option<&P>, buffer: B, cancellable: Option<&C>, ) -> Result<usize, glib::Error>92 fn send_to<B: AsRef<[u8]>, P: IsA<SocketAddress>, C: IsA<Cancellable>>( 93 &self, 94 address: Option<&P>, 95 buffer: B, 96 cancellable: Option<&C>, 97 ) -> Result<usize, glib::Error>; 98 #[doc(alias = "g_socket_send_with_blocking")] send_with_blocking<B: AsRef<[u8]>, C: IsA<Cancellable>>( &self, buffer: B, blocking: bool, cancellable: Option<&C>, ) -> Result<usize, glib::Error>99 fn send_with_blocking<B: AsRef<[u8]>, C: IsA<Cancellable>>( 100 &self, 101 buffer: B, 102 blocking: bool, 103 cancellable: Option<&C>, 104 ) -> Result<usize, glib::Error>; 105 106 #[cfg(any(unix, feature = "dox"))] 107 #[cfg_attr(feature = "dox", doc(cfg(unix)))] 108 #[doc(alias = "get_fd")] 109 #[doc(alias = "g_socket_get_fd")] fd<T: FromRawFd>(&self) -> T110 fn fd<T: FromRawFd>(&self) -> T; 111 112 #[cfg(any(windows, feature = "dox"))] 113 #[cfg_attr(feature = "dox", doc(cfg(windows)))] 114 #[doc(alias = "get_socket")] 115 #[doc(alias = "g_socket_get_fd")] socket<T: FromRawSocket>(&self) -> T116 fn socket<T: FromRawSocket>(&self) -> T; 117 118 #[doc(alias = "g_socket_create_source")] create_source<F, C>( &self, condition: glib::IOCondition, cancellable: Option<&C>, name: Option<&str>, priority: glib::Priority, func: F, ) -> glib::Source where F: FnMut(&Self, glib::IOCondition) -> glib::Continue + 'static, C: IsA<Cancellable>119 fn create_source<F, C>( 120 &self, 121 condition: glib::IOCondition, 122 cancellable: Option<&C>, 123 name: Option<&str>, 124 priority: glib::Priority, 125 func: F, 126 ) -> glib::Source 127 where 128 F: FnMut(&Self, glib::IOCondition) -> glib::Continue + 'static, 129 C: IsA<Cancellable>; 130 create_source_future<C: IsA<Cancellable>>( &self, condition: glib::IOCondition, cancellable: Option<&C>, priority: glib::Priority, ) -> Pin<Box<dyn std::future::Future<Output = glib::IOCondition> + 'static>>131 fn create_source_future<C: IsA<Cancellable>>( 132 &self, 133 condition: glib::IOCondition, 134 cancellable: Option<&C>, 135 priority: glib::Priority, 136 ) -> Pin<Box<dyn std::future::Future<Output = glib::IOCondition> + 'static>>; 137 create_source_stream<C: IsA<Cancellable>>( &self, condition: glib::IOCondition, cancellable: Option<&C>, priority: glib::Priority, ) -> Pin<Box<dyn Stream<Item = glib::IOCondition> + 'static>>138 fn create_source_stream<C: IsA<Cancellable>>( 139 &self, 140 condition: glib::IOCondition, 141 cancellable: Option<&C>, 142 priority: glib::Priority, 143 ) -> Pin<Box<dyn Stream<Item = glib::IOCondition> + 'static>>; 144 } 145 146 impl<O: IsA<Socket>> SocketExtManual for O { receive<B: AsMut<[u8]>, C: IsA<Cancellable>>( &self, mut buffer: B, cancellable: Option<&C>, ) -> Result<usize, glib::Error>147 fn receive<B: AsMut<[u8]>, C: IsA<Cancellable>>( 148 &self, 149 mut buffer: B, 150 cancellable: Option<&C>, 151 ) -> Result<usize, glib::Error> { 152 let cancellable = cancellable.map(|c| c.as_ref()); 153 let gcancellable = cancellable.to_glib_none(); 154 let buffer = buffer.as_mut(); 155 let buffer_ptr = buffer.as_mut_ptr(); 156 let count = buffer.len(); 157 unsafe { 158 let mut error = ptr::null_mut(); 159 let ret = ffi::g_socket_receive( 160 self.as_ref().to_glib_none().0, 161 buffer_ptr, 162 count, 163 gcancellable.0, 164 &mut error, 165 ); 166 if error.is_null() { 167 Ok(ret as usize) 168 } else { 169 Err(from_glib_full(error)) 170 } 171 } 172 } 173 receive_from<B: AsMut<[u8]>, C: IsA<Cancellable>>( &self, mut buffer: B, cancellable: Option<&C>, ) -> Result<(usize, SocketAddress), glib::Error>174 fn receive_from<B: AsMut<[u8]>, C: IsA<Cancellable>>( 175 &self, 176 mut buffer: B, 177 cancellable: Option<&C>, 178 ) -> Result<(usize, SocketAddress), glib::Error> { 179 let cancellable = cancellable.map(|c| c.as_ref()); 180 let gcancellable = cancellable.to_glib_none(); 181 let buffer = buffer.as_mut(); 182 let buffer_ptr = buffer.as_mut_ptr(); 183 let count = buffer.len(); 184 unsafe { 185 let mut error = ptr::null_mut(); 186 let mut addr_ptr = ptr::null_mut(); 187 188 let ret = ffi::g_socket_receive_from( 189 self.as_ref().to_glib_none().0, 190 &mut addr_ptr, 191 buffer_ptr, 192 count, 193 gcancellable.0, 194 &mut error, 195 ); 196 if error.is_null() { 197 Ok((ret as usize, from_glib_full(addr_ptr))) 198 } else { 199 Err(from_glib_full(error)) 200 } 201 } 202 } 203 receive_with_blocking<B: AsMut<[u8]>, C: IsA<Cancellable>>( &self, mut buffer: B, blocking: bool, cancellable: Option<&C>, ) -> Result<usize, glib::Error>204 fn receive_with_blocking<B: AsMut<[u8]>, C: IsA<Cancellable>>( 205 &self, 206 mut buffer: B, 207 blocking: bool, 208 cancellable: Option<&C>, 209 ) -> Result<usize, glib::Error> { 210 let cancellable = cancellable.map(|c| c.as_ref()); 211 let gcancellable = cancellable.to_glib_none(); 212 let buffer = buffer.as_mut(); 213 let buffer_ptr = buffer.as_mut_ptr(); 214 let count = buffer.len(); 215 unsafe { 216 let mut error = ptr::null_mut(); 217 let ret = ffi::g_socket_receive_with_blocking( 218 self.as_ref().to_glib_none().0, 219 buffer_ptr, 220 count, 221 blocking.into_glib(), 222 gcancellable.0, 223 &mut error, 224 ); 225 if error.is_null() { 226 Ok(ret as usize) 227 } else { 228 Err(from_glib_full(error)) 229 } 230 } 231 } 232 send<B: AsRef<[u8]>, C: IsA<Cancellable>>( &self, buffer: B, cancellable: Option<&C>, ) -> Result<usize, glib::Error>233 fn send<B: AsRef<[u8]>, C: IsA<Cancellable>>( 234 &self, 235 buffer: B, 236 cancellable: Option<&C>, 237 ) -> Result<usize, glib::Error> { 238 let cancellable = cancellable.map(|c| c.as_ref()); 239 let gcancellable = cancellable.to_glib_none(); 240 let (count, buffer_ptr) = { 241 let slice = buffer.as_ref(); 242 (slice.len(), slice.as_ptr()) 243 }; 244 unsafe { 245 let mut error = ptr::null_mut(); 246 let ret = ffi::g_socket_send( 247 self.as_ref().to_glib_none().0, 248 mut_override(buffer_ptr), 249 count, 250 gcancellable.0, 251 &mut error, 252 ); 253 if error.is_null() { 254 Ok(ret as usize) 255 } else { 256 Err(from_glib_full(error)) 257 } 258 } 259 } 260 send_to<B: AsRef<[u8]>, P: IsA<SocketAddress>, C: IsA<Cancellable>>( &self, address: Option<&P>, buffer: B, cancellable: Option<&C>, ) -> Result<usize, glib::Error>261 fn send_to<B: AsRef<[u8]>, P: IsA<SocketAddress>, C: IsA<Cancellable>>( 262 &self, 263 address: Option<&P>, 264 buffer: B, 265 cancellable: Option<&C>, 266 ) -> Result<usize, glib::Error> { 267 let cancellable = cancellable.map(|c| c.as_ref()); 268 let gcancellable = cancellable.to_glib_none(); 269 let (count, buffer_ptr) = { 270 let slice = buffer.as_ref(); 271 (slice.len(), slice.as_ptr()) 272 }; 273 unsafe { 274 let mut error = ptr::null_mut(); 275 276 let ret = ffi::g_socket_send_to( 277 self.as_ref().to_glib_none().0, 278 address.map(|p| p.as_ref()).to_glib_none().0, 279 mut_override(buffer_ptr), 280 count, 281 gcancellable.0, 282 &mut error, 283 ); 284 if error.is_null() { 285 Ok(ret as usize) 286 } else { 287 Err(from_glib_full(error)) 288 } 289 } 290 } 291 send_with_blocking<B: AsRef<[u8]>, C: IsA<Cancellable>>( &self, buffer: B, blocking: bool, cancellable: Option<&C>, ) -> Result<usize, glib::Error>292 fn send_with_blocking<B: AsRef<[u8]>, C: IsA<Cancellable>>( 293 &self, 294 buffer: B, 295 blocking: bool, 296 cancellable: Option<&C>, 297 ) -> Result<usize, glib::Error> { 298 let cancellable = cancellable.map(|c| c.as_ref()); 299 let gcancellable = cancellable.to_glib_none(); 300 let (count, buffer_ptr) = { 301 let slice = buffer.as_ref(); 302 (slice.len(), slice.as_ptr()) 303 }; 304 unsafe { 305 let mut error = ptr::null_mut(); 306 let ret = ffi::g_socket_send_with_blocking( 307 self.as_ref().to_glib_none().0, 308 mut_override(buffer_ptr), 309 count, 310 blocking.into_glib(), 311 gcancellable.0, 312 &mut error, 313 ); 314 if error.is_null() { 315 Ok(ret as usize) 316 } else { 317 Err(from_glib_full(error)) 318 } 319 } 320 } 321 322 #[cfg(any(unix, feature = "dox"))] 323 #[cfg_attr(feature = "dox", doc(cfg(unix)))] fd<T: FromRawFd>(&self) -> T324 fn fd<T: FromRawFd>(&self) -> T { 325 unsafe { FromRawFd::from_raw_fd(ffi::g_socket_get_fd(self.as_ref().to_glib_none().0)) } 326 } 327 328 #[cfg(any(windows, feature = "dox"))] 329 #[cfg_attr(feature = "dox", doc(cfg(windows)))] socket<T: FromRawSocket>(&self) -> T330 fn socket<T: FromRawSocket>(&self) -> T { 331 unsafe { 332 FromRawSocket::from_raw_socket(ffi::g_socket_get_fd(self.as_ref().to_glib_none().0) as _) 333 } 334 } 335 create_source<F, C>( &self, condition: glib::IOCondition, cancellable: Option<&C>, name: Option<&str>, priority: glib::Priority, func: F, ) -> glib::Source where F: FnMut(&Self, glib::IOCondition) -> glib::Continue + 'static, C: IsA<Cancellable>,336 fn create_source<F, C>( 337 &self, 338 condition: glib::IOCondition, 339 cancellable: Option<&C>, 340 name: Option<&str>, 341 priority: glib::Priority, 342 func: F, 343 ) -> glib::Source 344 where 345 F: FnMut(&Self, glib::IOCondition) -> glib::Continue + 'static, 346 C: IsA<Cancellable>, 347 { 348 unsafe extern "C" fn trampoline< 349 O: IsA<Socket>, 350 F: FnMut(&O, glib::IOCondition) -> glib::Continue + 'static, 351 >( 352 socket: *mut ffi::GSocket, 353 condition: glib::ffi::GIOCondition, 354 func: glib::ffi::gpointer, 355 ) -> glib::ffi::gboolean { 356 let func: &RefCell<F> = &*(func as *const RefCell<F>); 357 let mut func = func.borrow_mut(); 358 (&mut *func)( 359 Socket::from_glib_borrow(socket).unsafe_cast_ref(), 360 from_glib(condition), 361 ) 362 .into_glib() 363 } 364 unsafe extern "C" fn destroy_closure<O, F>(ptr: glib::ffi::gpointer) { 365 Box::<RefCell<F>>::from_raw(ptr as *mut _); 366 } 367 let cancellable = cancellable.map(|c| c.as_ref()); 368 let gcancellable = cancellable.to_glib_none(); 369 unsafe { 370 let source = ffi::g_socket_create_source( 371 self.as_ref().to_glib_none().0, 372 condition.into_glib(), 373 gcancellable.0, 374 ); 375 let trampoline = trampoline::<O, F> as glib::ffi::gpointer; 376 glib::ffi::g_source_set_callback( 377 source, 378 Some(transmute::< 379 _, 380 unsafe extern "C" fn(glib::ffi::gpointer) -> glib::ffi::gboolean, 381 >(trampoline)), 382 Box::into_raw(Box::new(RefCell::new(func))) as glib::ffi::gpointer, 383 Some(destroy_closure::<O, F>), 384 ); 385 glib::ffi::g_source_set_priority(source, priority.into_glib()); 386 387 if let Some(name) = name { 388 glib::ffi::g_source_set_name(source, name.to_glib_none().0); 389 } 390 391 from_glib_full(source) 392 } 393 } 394 create_source_future<C: IsA<Cancellable>>( &self, condition: glib::IOCondition, cancellable: Option<&C>, priority: glib::Priority, ) -> Pin<Box<dyn std::future::Future<Output = glib::IOCondition> + 'static>>395 fn create_source_future<C: IsA<Cancellable>>( 396 &self, 397 condition: glib::IOCondition, 398 cancellable: Option<&C>, 399 priority: glib::Priority, 400 ) -> Pin<Box<dyn std::future::Future<Output = glib::IOCondition> + 'static>> { 401 let cancellable: Option<Cancellable> = cancellable.map(|c| c.as_ref()).cloned(); 402 403 let obj = self.clone(); 404 Box::pin(glib::SourceFuture::new(move |send| { 405 let mut send = Some(send); 406 obj.create_source( 407 condition, 408 cancellable.as_ref(), 409 None, 410 priority, 411 move |_, condition| { 412 let _ = send.take().unwrap().send(condition); 413 glib::Continue(false) 414 }, 415 ) 416 })) 417 } 418 create_source_stream<C: IsA<Cancellable>>( &self, condition: glib::IOCondition, cancellable: Option<&C>, priority: glib::Priority, ) -> Pin<Box<dyn Stream<Item = glib::IOCondition> + 'static>>419 fn create_source_stream<C: IsA<Cancellable>>( 420 &self, 421 condition: glib::IOCondition, 422 cancellable: Option<&C>, 423 priority: glib::Priority, 424 ) -> Pin<Box<dyn Stream<Item = glib::IOCondition> + 'static>> { 425 let cancellable: Option<Cancellable> = cancellable.map(|c| c.as_ref()).cloned(); 426 427 let obj = self.clone(); 428 Box::pin(glib::SourceStream::new(move |send| { 429 let send = Some(send); 430 obj.create_source( 431 condition, 432 cancellable.as_ref(), 433 None, 434 priority, 435 move |_, condition| { 436 if send.as_ref().unwrap().unbounded_send(condition).is_err() { 437 glib::Continue(false) 438 } else { 439 glib::Continue(true) 440 } 441 }, 442 ) 443 })) 444 } 445 } 446 447 #[cfg(all(not(unix), feature = "dox"))] 448 pub trait IntoRawFd { into_raw_fd(self) -> c_int449 fn into_raw_fd(self) -> c_int; 450 } 451 452 #[cfg(all(not(unix), feature = "dox"))] 453 pub trait FromRawFd { from_raw_fd(fd: c_int) -> Self454 unsafe fn from_raw_fd(fd: c_int) -> Self; 455 } 456 457 #[cfg(all(not(unix), feature = "dox"))] 458 pub trait AsRawFd { as_raw_fd(&self) -> RawFd459 fn as_raw_fd(&self) -> RawFd; 460 } 461 462 #[cfg(all(not(unix), feature = "dox"))] 463 pub type RawFd = c_int; 464 465 #[cfg(all(not(windows), feature = "dox"))] 466 pub trait IntoRawSocket { into_raw_socket(self) -> u64467 fn into_raw_socket(self) -> u64; 468 } 469 470 #[cfg(all(not(windows), feature = "dox"))] 471 pub trait FromRawSocket { from_raw_socket(sock: u64) -> Self472 unsafe fn from_raw_socket(sock: u64) -> Self; 473 } 474 475 #[cfg(all(not(windows), feature = "dox"))] 476 pub trait AsRawSocket { as_raw_socket(&self) -> RawSocket477 fn as_raw_socket(&self) -> RawSocket; 478 } 479 480 #[cfg(all(not(windows), feature = "dox"))] 481 pub type RawSocket = *mut c_void; 482