gio/
socket.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
// Take a look at the license at the top of the repository in the LICENSE file.

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
#[cfg(feature = "v2_60")]
use std::time::Duration;
use std::{cell::RefCell, marker::PhantomData, mem::transmute, pin::Pin, ptr};

use futures_core::stream::Stream;
use glib::{prelude::*, translate::*, Slice};

#[cfg(feature = "v2_60")]
use crate::PollableReturn;
use crate::{ffi, Cancellable, Socket, SocketAddress, SocketControlMessage};

impl Socket {
    /// Creates a new #GSocket from a native file descriptor
    /// or winsock SOCKET handle.
    ///
    /// This reads all the settings from the file descriptor so that
    /// all properties should work. Note that the file descriptor
    /// will be set to non-blocking mode, independent on the blocking
    /// mode of the #GSocket.
    ///
    /// On success, the returned #GSocket takes ownership of @fd. On failure, the
    /// caller must close @fd themselves.
    ///
    /// Since GLib 2.46, it is no longer a fatal error to call this on a non-socket
    /// descriptor.  Instead, a GError will be set with code [`IOErrorEnum::Failed`][crate::IOErrorEnum::Failed]
    /// ## `fd`
    /// a native socket file descriptor.
    ///
    /// # Returns
    ///
    /// a #GSocket or [`None`] on error.
    ///     Free the returned object with g_object_unref().
    #[cfg(unix)]
    #[cfg_attr(docsrs, doc(cfg(unix)))]
    #[allow(clippy::missing_safety_doc)]
    pub unsafe fn from_fd(fd: impl IntoRawFd) -> Result<Socket, glib::Error> {
        let fd = fd.into_raw_fd();
        let mut error = ptr::null_mut();
        let ret = ffi::g_socket_new_from_fd(fd, &mut error);
        if error.is_null() {
            Ok(from_glib_full(ret))
        } else {
            Err(from_glib_full(error))
        }
    }
    #[cfg(windows)]
    #[cfg_attr(docsrs, doc(cfg(windows)))]
    #[allow(clippy::missing_safety_doc)]
    pub unsafe fn from_socket(socket: impl IntoRawSocket) -> Result<Socket, glib::Error> {
        let socket = socket.into_raw_socket();
        let mut error = ptr::null_mut();
        let ret = ffi::g_socket_new_from_fd(socket as i32, &mut error);
        if error.is_null() {
            Ok(from_glib_full(ret))
        } else {
            Err(from_glib_full(error))
        }
    }
}

#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
impl AsRawFd for Socket {
    fn as_raw_fd(&self) -> RawFd {
        unsafe { ffi::g_socket_get_fd(self.to_glib_none().0) as _ }
    }
}

#[cfg(windows)]
#[cfg_attr(docsrs, doc(cfg(windows)))]
impl AsRawSocket for Socket {
    fn as_raw_socket(&self) -> RawSocket {
        unsafe { ffi::g_socket_get_fd(self.to_glib_none().0) as _ }
    }
}

#[doc(alias = "GInputVector")]
#[repr(transparent)]
#[derive(Debug)]
pub struct InputVector<'v> {
    vector: ffi::GInputVector,
    buffer: PhantomData<&'v mut [u8]>,
}

impl<'v> InputVector<'v> {
    #[inline]
    pub fn new(buffer: &'v mut [u8]) -> Self {
        Self {
            vector: ffi::GInputVector {
                buffer: buffer.as_mut_ptr() as *mut _,
                size: buffer.len(),
            },
            buffer: PhantomData,
        }
    }
}

unsafe impl Send for InputVector<'_> {}
unsafe impl Sync for InputVector<'_> {}

impl std::ops::Deref for InputVector<'_> {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe { std::slice::from_raw_parts(self.vector.buffer as *const _, self.vector.size) }
    }
}

impl std::ops::DerefMut for InputVector<'_> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { std::slice::from_raw_parts_mut(self.vector.buffer as *mut _, self.vector.size) }
    }
}

#[derive(Debug)]
pub struct SocketControlMessages {
    ptr: *mut *mut ffi::GSocketControlMessage,
    len: u32,
}

impl SocketControlMessages {
    #[inline]
    pub const fn new() -> Self {
        Self {
            ptr: ptr::null_mut(),
            len: 0,
        }
    }
}

impl AsRef<[SocketControlMessage]> for SocketControlMessages {
    #[inline]
    fn as_ref(&self) -> &[SocketControlMessage] {
        unsafe { std::slice::from_raw_parts(self.ptr as *const _, self.len as usize) }
    }
}

impl std::ops::Deref for SocketControlMessages {
    type Target = [SocketControlMessage];

    #[inline]
    fn deref(&self) -> &Self::Target {
        self.as_ref()
    }
}

impl Default for SocketControlMessages {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for SocketControlMessages {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let _: Slice<SocketControlMessage> =
                Slice::from_glib_full_num(self.ptr as *mut _, self.len as usize);
        }
    }
}

/// Structure used for scatter/gather data input when receiving multiple
/// messages or packets in one go. You generally pass in an array of empty
/// #GInputVectors and the operation will use all the buffers as if they
/// were one buffer, and will set @bytes_received to the total number of bytes
/// received across all #GInputVectors.
///
/// This structure closely mirrors `struct mmsghdr` and `struct msghdr` from
/// the POSIX sockets API (see `man 2 recvmmsg`).
///
/// If @address is non-[`None`] then it is set to the source address the message
/// was received from, and the caller must free it afterwards.
///
/// If @control_messages is non-[`None`] then it is set to an array of control
/// messages received with the message (if any), and the caller must free it
/// afterwards. @num_control_messages is set to the number of elements in
/// this array, which may be zero.
///
/// Flags relevant to this message will be returned in @flags. For example,
/// `MSG_EOR` or `MSG_TRUNC`.
#[doc(alias = "GInputMessage")]
#[repr(transparent)]
#[derive(Debug)]
pub struct InputMessage<'m> {
    message: ffi::GInputMessage,
    address: PhantomData<Option<&'m mut Option<SocketAddress>>>,
    vectors: PhantomData<&'m mut [InputVector<'m>]>,
    control_messages: PhantomData<Option<&'m mut SocketControlMessages>>,
}

impl<'m> InputMessage<'m> {
    pub fn new(
        mut address: Option<&'m mut Option<SocketAddress>>,
        vectors: &'m mut [InputVector<'m>],
        control_messages: Option<&'m mut SocketControlMessages>,
    ) -> Self {
        let address = address
            .as_mut()
            .map(|a| {
                assert!(a.is_none());
                *a as *mut _ as *mut _
            })
            .unwrap_or_else(ptr::null_mut);
        let (control_messages, num_control_messages) = control_messages
            .map(|c| (&mut c.ptr as *mut _, &mut c.len as *mut _))
            .unwrap_or_else(|| (ptr::null_mut(), ptr::null_mut()));
        Self {
            message: ffi::GInputMessage {
                address,
                vectors: vectors.as_mut_ptr() as *mut ffi::GInputVector,
                num_vectors: vectors.len().try_into().unwrap(),
                bytes_received: 0,
                flags: 0,
                control_messages,
                num_control_messages,
            },
            address: PhantomData,
            vectors: PhantomData,
            control_messages: PhantomData,
        }
    }
    #[inline]
    pub fn vectors(&mut self) -> &'m mut [InputVector<'m>] {
        unsafe {
            std::slice::from_raw_parts_mut(
                self.message.vectors as *mut _,
                self.message.num_vectors as usize,
            )
        }
    }
    #[inline]
    pub const fn flags(&self) -> i32 {
        self.message.flags
    }
    #[inline]
    pub const fn bytes_received(&self) -> usize {
        self.message.bytes_received
    }
}

#[doc(alias = "GOutputVector")]
#[repr(transparent)]
#[derive(Debug)]
pub struct OutputVector<'v> {
    vector: ffi::GOutputVector,
    buffer: PhantomData<&'v [u8]>,
}

impl<'v> OutputVector<'v> {
    #[inline]
    pub const fn new(buffer: &'v [u8]) -> Self {
        Self {
            vector: ffi::GOutputVector {
                buffer: buffer.as_ptr() as *const _,
                size: buffer.len(),
            },
            buffer: PhantomData,
        }
    }
}

unsafe impl Send for OutputVector<'_> {}
unsafe impl Sync for OutputVector<'_> {}

impl std::ops::Deref for OutputVector<'_> {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &Self::Target {
        unsafe { std::slice::from_raw_parts(self.vector.buffer as *const _, self.vector.size) }
    }
}

/// Structure used for scatter/gather data output when sending multiple
/// messages or packets in one go. You generally pass in an array of
/// #GOutputVectors and the operation will use all the buffers as if they
/// were one buffer.
///
/// If @address is [`None`] then the message is sent to the default receiver
/// (as previously set by g_socket_connect()).
#[doc(alias = "GOutputMessage")]
#[repr(transparent)]
#[derive(Debug)]
pub struct OutputMessage<'m> {
    message: ffi::GOutputMessage,
    address: PhantomData<Option<&'m SocketAddress>>,
    vectors: PhantomData<&'m [OutputVector<'m>]>,
    control_messages: PhantomData<&'m [SocketControlMessage]>,
}

impl<'m> OutputMessage<'m> {
    pub fn new<A: IsA<SocketAddress>>(
        address: Option<&'m A>,
        vectors: &'m [OutputVector<'m>],
        control_messages: &'m [SocketControlMessage],
    ) -> Self {
        Self {
            message: ffi::GOutputMessage {
                address: address
                    .map(|a| a.upcast_ref::<SocketAddress>().as_ptr())
                    .unwrap_or_else(ptr::null_mut),
                vectors: mut_override(vectors.as_ptr() as *const ffi::GOutputVector),
                num_vectors: vectors.len().try_into().unwrap(),
                bytes_sent: 0,
                control_messages: control_messages.as_ptr() as *mut _,
                num_control_messages: control_messages.len().try_into().unwrap(),
            },
            address: PhantomData,
            vectors: PhantomData,
            control_messages: PhantomData,
        }
    }
    #[inline]
    pub fn vectors(&self) -> &'m [OutputVector<'m>] {
        unsafe {
            std::slice::from_raw_parts(
                self.message.vectors as *const _,
                self.message.num_vectors as usize,
            )
        }
    }
    #[inline]
    pub fn bytes_sent(&self) -> u32 {
        self.message.bytes_sent
    }
}

mod sealed {
    pub trait Sealed {}
    impl<T: super::IsA<super::Socket>> Sealed for T {}
}

pub trait SocketExtManual: sealed::Sealed + IsA<Socket> + Sized {
    /// Receive data (up to @size bytes) from a socket. This is mainly used by
    /// connection-oriented sockets; it is identical to g_socket_receive_from()
    /// with @address set to [`None`].
    ///
    /// For [`SocketType::Datagram`][crate::SocketType::Datagram] and [`SocketType::Seqpacket`][crate::SocketType::Seqpacket] sockets,
    /// g_socket_receive() will always read either 0 or 1 complete messages from
    /// the socket. If the received message is too large to fit in @buffer, then
    /// the data beyond @size bytes will be discarded, without any explicit
    /// indication that this has occurred.
    ///
    /// For [`SocketType::Stream`][crate::SocketType::Stream] sockets, g_socket_receive() can return any
    /// number of bytes, up to @size. If more than @size bytes have been
    /// received, the additional data will be returned in future calls to
    /// g_socket_receive().
    ///
    /// If the socket is in blocking mode the call will block until there
    /// is some data to receive, the connection is closed, or there is an
    /// error. If there is no data available and the socket is in
    /// non-blocking mode, a [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] error will be
    /// returned. To be notified when data is available, wait for the
    /// [`glib::IOCondition::IN`][crate::glib::IOCondition::IN] condition.
    ///
    /// On error -1 is returned and @error is set accordingly.
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes read, or 0 if the connection was closed by
    /// the peer, or -1 on error
    ///
    /// ## `buffer`
    ///
    ///     a buffer to read data into (which should be at least @size bytes long).
    #[doc(alias = "g_socket_receive")]
    fn receive<B: AsMut<[u8]>, C: IsA<Cancellable>>(
        &self,
        mut buffer: B,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        let gcancellable = cancellable.to_glib_none();
        let buffer = buffer.as_mut();
        let buffer_ptr = buffer.as_mut_ptr();
        let count = buffer.len();
        unsafe {
            let mut error = ptr::null_mut();
            let ret = ffi::g_socket_receive(
                self.as_ref().to_glib_none().0,
                buffer_ptr,
                count,
                gcancellable.0,
                &mut error,
            );
            if error.is_null() {
                Ok(ret as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// Receive data (up to @size bytes) from a socket.
    ///
    /// If @address is non-[`None`] then @address will be set equal to the
    /// source address of the received packet.
    /// @address is owned by the caller.
    ///
    /// See g_socket_receive() for additional information.
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes read, or 0 if the connection was closed by
    /// the peer, or -1 on error
    ///
    /// ## `address`
    /// a pointer to a #GSocketAddress
    ///     pointer, or [`None`]
    ///
    /// ## `buffer`
    ///
    ///     a buffer to read data into (which should be at least @size bytes long).
    #[doc(alias = "g_socket_receive_from")]
    fn receive_from<B: AsMut<[u8]>, C: IsA<Cancellable>>(
        &self,
        mut buffer: B,
        cancellable: Option<&C>,
    ) -> Result<(usize, SocketAddress), glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        let gcancellable = cancellable.to_glib_none();
        let buffer = buffer.as_mut();
        let buffer_ptr = buffer.as_mut_ptr();
        let count = buffer.len();
        unsafe {
            let mut error = ptr::null_mut();
            let mut addr_ptr = ptr::null_mut();

            let ret = ffi::g_socket_receive_from(
                self.as_ref().to_glib_none().0,
                &mut addr_ptr,
                buffer_ptr,
                count,
                gcancellable.0,
                &mut error,
            );
            if error.is_null() {
                Ok((ret as usize, from_glib_full(addr_ptr)))
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// Receive data from a socket.  For receiving multiple messages, see
    /// g_socket_receive_messages(); for easier use, see
    /// g_socket_receive() and g_socket_receive_from().
    ///
    /// If @address is non-[`None`] then @address will be set equal to the
    /// source address of the received packet.
    /// @address is owned by the caller.
    ///
    /// @vector must point to an array of #GInputVector structs and
    /// @num_vectors must be the length of this array.  These structs
    /// describe the buffers that received data will be scattered into.
    /// If @num_vectors is -1, then @vectors is assumed to be terminated
    /// by a #GInputVector with a [`None`] buffer pointer.
    ///
    /// As a special case, if @num_vectors is 0 (in which case, @vectors
    /// may of course be [`None`]), then a single byte is received and
    /// discarded. This is to facilitate the common practice of sending a
    /// single '\0' byte for the purposes of transferring ancillary data.
    ///
    /// @messages, if non-[`None`], will be set to point to a newly-allocated
    /// array of #GSocketControlMessage instances or [`None`] if no such
    /// messages was received. These correspond to the control messages
    /// received from the kernel, one #GSocketControlMessage per message
    /// from the kernel. This array is [`None`]-terminated and must be freed
    /// by the caller using g_free() after calling g_object_unref() on each
    /// element. If @messages is [`None`], any control messages received will
    /// be discarded.
    ///
    /// @num_messages, if non-[`None`], will be set to the number of control
    /// messages received.
    ///
    /// If both @messages and @num_messages are non-[`None`], then
    /// @num_messages gives the number of #GSocketControlMessage instances
    /// in @messages (ie: not including the [`None`] terminator).
    ///
    /// @flags is an in/out parameter. The commonly available arguments
    /// for this are available in the #GSocketMsgFlags enum, but the
    /// values there are the same as the system values, and the flags
    /// are passed in as-is, so you can pass in system-specific flags too
    /// (and g_socket_receive_message() may pass system-specific flags out).
    /// Flags passed in to the parameter affect the receive operation; flags returned
    /// out of it are relevant to the specific returned message.
    ///
    /// As with g_socket_receive(), data may be discarded if @self is
    /// [`SocketType::Datagram`][crate::SocketType::Datagram] or [`SocketType::Seqpacket`][crate::SocketType::Seqpacket] and you do not
    /// provide enough buffer space to read a complete message. You can pass
    /// [`SocketMsgFlags::PEEK`][crate::SocketMsgFlags::PEEK] in @flags to peek at the current message without
    /// removing it from the receive queue, but there is no portable way to find
    /// out the length of the message other than by reading it into a
    /// sufficiently-large buffer.
    ///
    /// If the socket is in blocking mode the call will block until there
    /// is some data to receive, the connection is closed, or there is an
    /// error. If there is no data available and the socket is in
    /// non-blocking mode, a [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] error will be
    /// returned. To be notified when data is available, wait for the
    /// [`glib::IOCondition::IN`][crate::glib::IOCondition::IN] condition.
    ///
    /// On error -1 is returned and @error is set accordingly.
    /// ## `vectors`
    /// an array of #GInputVector structs
    /// ## `flags`
    /// a pointer to an int containing #GSocketMsgFlags flags,
    ///    which may additionally contain
    ///    [other platform specific flags](http://man7.org/linux/man-pages/man2/recv.2.html)
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes read, or 0 if the connection was closed by
    /// the peer, or -1 on error
    ///
    /// ## `address`
    /// a pointer to a #GSocketAddress
    ///     pointer, or [`None`]
    ///
    /// ## `messages`
    /// a pointer
    ///    which may be filled with an array of #GSocketControlMessages, or [`None`]
    #[doc(alias = "g_socket_receive_message")]
    fn receive_message<C: IsA<Cancellable>>(
        &self,
        mut address: Option<&mut Option<SocketAddress>>,
        vectors: &mut [InputVector],
        control_messages: Option<&mut SocketControlMessages>,
        mut flags: i32,
        cancellable: Option<&C>,
    ) -> Result<(usize, i32), glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        let address = address
            .as_mut()
            .map(|a| {
                assert!(a.is_none());
                *a as *mut _ as *mut _
            })
            .unwrap_or_else(ptr::null_mut);
        let (control_messages, num_control_messages) = control_messages
            .map(|c| (&mut c.ptr as *mut _, &mut c.len as *mut _ as *mut _))
            .unwrap_or_else(|| (ptr::null_mut(), ptr::null_mut()));
        unsafe {
            let mut error = ptr::null_mut();

            let received = ffi::g_socket_receive_message(
                self.as_ref().to_glib_none().0,
                address,
                vectors.as_mut_ptr() as *mut ffi::GInputVector,
                vectors.len().try_into().unwrap(),
                control_messages,
                num_control_messages,
                &mut flags,
                cancellable.to_glib_none().0,
                &mut error,
            );
            if error.is_null() {
                Ok((received as usize, flags))
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// Receive multiple data messages from @self in one go.  This is the most
    /// complicated and fully-featured version of this call. For easier use, see
    /// g_socket_receive(), g_socket_receive_from(), and g_socket_receive_message().
    ///
    /// @messages must point to an array of #GInputMessage structs and
    /// @num_messages must be the length of this array. Each #GInputMessage
    /// contains a pointer to an array of #GInputVector structs describing the
    /// buffers that the data received in each message will be written to. Using
    /// multiple #GInputVectors is more memory-efficient than manually copying data
    /// out of a single buffer to multiple sources, and more system-call-efficient
    /// than making multiple calls to g_socket_receive(), such as in scenarios where
    /// a lot of data packets need to be received (e.g. high-bandwidth video
    /// streaming over RTP/UDP).
    ///
    /// @flags modify how all messages are received. The commonly available
    /// arguments for this are available in the #GSocketMsgFlags enum, but the
    /// values there are the same as the system values, and the flags
    /// are passed in as-is, so you can pass in system-specific flags too. These
    /// flags affect the overall receive operation. Flags affecting individual
    /// messages are returned in #GInputMessage.flags.
    ///
    /// The other members of #GInputMessage are treated as described in its
    /// documentation.
    ///
    /// If #GSocket:blocking is [`true`] the call will block until @num_messages have
    /// been received, or the end of the stream is reached.
    ///
    /// If #GSocket:blocking is [`false`] the call will return up to @num_messages
    /// without blocking, or [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] if no messages are queued in the
    /// operating system to be received.
    ///
    /// In blocking mode, if #GSocket:timeout is positive and is reached before any
    /// messages are received, [`IOErrorEnum::TimedOut`][crate::IOErrorEnum::TimedOut] is returned, otherwise up to
    /// @num_messages are returned. (Note: This is effectively the
    /// behaviour of `MSG_WAITFORONE` with recvmmsg().)
    ///
    /// To be notified when messages are available, wait for the
    /// [`glib::IOCondition::IN`][crate::glib::IOCondition::IN] condition. Note though that you may still receive
    /// [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] from g_socket_receive_messages() even if you were
    /// previously notified of a [`glib::IOCondition::IN`][crate::glib::IOCondition::IN] condition.
    ///
    /// If the remote peer closes the connection, any messages queued in the
    /// operating system will be returned, and subsequent calls to
    /// g_socket_receive_messages() will return 0 (with no error set).
    ///
    /// On error -1 is returned and @error is set accordingly. An error will only
    /// be returned if zero messages could be received; otherwise the number of
    /// messages successfully received before the error will be returned.
    /// ## `messages`
    /// an array of #GInputMessage structs
    /// ## `flags`
    /// an int containing #GSocketMsgFlags flags for the overall operation,
    ///    which may additionally contain
    ///    [other platform specific flags](http://man7.org/linux/man-pages/man2/recv.2.html)
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// number of messages received, or -1 on error. Note that the number
    ///     of messages received may be smaller than @num_messages if in non-blocking
    ///     mode, if the peer closed the connection, or if @num_messages
    ///     was larger than `UIO_MAXIOV` (1024), in which case the caller may re-try
    ///     to receive the remaining messages.
    #[doc(alias = "g_socket_receive_messages")]
    fn receive_messages<C: IsA<Cancellable>>(
        &self,
        messages: &mut [InputMessage],
        flags: i32,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        unsafe {
            let mut error = ptr::null_mut();

            let count = ffi::g_socket_receive_messages(
                self.as_ref().to_glib_none().0,
                messages.as_mut_ptr() as *mut _,
                messages.len().try_into().unwrap(),
                flags,
                cancellable.to_glib_none().0,
                &mut error,
            );
            if error.is_null() {
                Ok(count as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// This behaves exactly the same as g_socket_receive(), except that
    /// the choice of blocking or non-blocking behavior is determined by
    /// the @blocking argument rather than by @self's properties.
    /// ## `blocking`
    /// whether to do blocking or non-blocking I/O
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes read, or 0 if the connection was closed by
    /// the peer, or -1 on error
    ///
    /// ## `buffer`
    ///
    ///     a buffer to read data into (which should be at least @size bytes long).
    #[doc(alias = "g_socket_receive_with_blocking")]
    fn receive_with_blocking<B: AsMut<[u8]>, C: IsA<Cancellable>>(
        &self,
        mut buffer: B,
        blocking: bool,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        let gcancellable = cancellable.to_glib_none();
        let buffer = buffer.as_mut();
        let buffer_ptr = buffer.as_mut_ptr();
        let count = buffer.len();
        unsafe {
            let mut error = ptr::null_mut();
            let ret = ffi::g_socket_receive_with_blocking(
                self.as_ref().to_glib_none().0,
                buffer_ptr,
                count,
                blocking.into_glib(),
                gcancellable.0,
                &mut error,
            );
            if error.is_null() {
                Ok(ret as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    /// Tries to send @size bytes from @buffer on the socket. This is
    /// mainly used by connection-oriented sockets; it is identical to
    /// g_socket_send_to() with @address set to [`None`].
    ///
    /// If the socket is in blocking mode the call will block until there is
    /// space for the data in the socket queue. If there is no space available
    /// and the socket is in non-blocking mode a [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] error
    /// will be returned. To be notified when space is available, wait for the
    /// [`glib::IOCondition::OUT`][crate::glib::IOCondition::OUT] condition. Note though that you may still receive
    /// [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] from g_socket_send() even if you were previously
    /// notified of a [`glib::IOCondition::OUT`][crate::glib::IOCondition::OUT] condition. (On Windows in particular, this is
    /// very common due to the way the underlying APIs work.)
    ///
    /// On error -1 is returned and @error is set accordingly.
    /// ## `buffer`
    /// the buffer
    ///     containing the data to send.
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes written (which may be less than @size), or -1
    /// on error
    #[doc(alias = "g_socket_send")]
    fn send<B: AsRef<[u8]>, C: IsA<Cancellable>>(
        &self,
        buffer: B,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        let gcancellable = cancellable.to_glib_none();
        let (count, buffer_ptr) = {
            let slice = buffer.as_ref();
            (slice.len(), slice.as_ptr())
        };
        unsafe {
            let mut error = ptr::null_mut();
            let ret = ffi::g_socket_send(
                self.as_ref().to_glib_none().0,
                mut_override(buffer_ptr),
                count,
                gcancellable.0,
                &mut error,
            );
            if error.is_null() {
                Ok(ret as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// Send data to @address on @self.  For sending multiple messages see
    /// g_socket_send_messages(); for easier use, see
    /// g_socket_send() and g_socket_send_to().
    ///
    /// If @address is [`None`] then the message is sent to the default receiver
    /// (set by g_socket_connect()).
    ///
    /// @vectors must point to an array of #GOutputVector structs and
    /// @num_vectors must be the length of this array. (If @num_vectors is -1,
    /// then @vectors is assumed to be terminated by a #GOutputVector with a
    /// [`None`] buffer pointer.) The #GOutputVector structs describe the buffers
    /// that the sent data will be gathered from. Using multiple
    /// #GOutputVectors is more memory-efficient than manually copying
    /// data from multiple sources into a single buffer, and more
    /// network-efficient than making multiple calls to g_socket_send().
    ///
    /// @messages, if non-[`None`], is taken to point to an array of @num_messages
    /// #GSocketControlMessage instances. These correspond to the control
    /// messages to be sent on the socket.
    /// If @num_messages is -1 then @messages is treated as a [`None`]-terminated
    /// array.
    ///
    /// @flags modify how the message is sent. The commonly available arguments
    /// for this are available in the #GSocketMsgFlags enum, but the
    /// values there are the same as the system values, and the flags
    /// are passed in as-is, so you can pass in system-specific flags too.
    ///
    /// If the socket is in blocking mode the call will block until there is
    /// space for the data in the socket queue. If there is no space available
    /// and the socket is in non-blocking mode a [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] error
    /// will be returned. To be notified when space is available, wait for the
    /// [`glib::IOCondition::OUT`][crate::glib::IOCondition::OUT] condition. Note though that you may still receive
    /// [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] from g_socket_send() even if you were previously
    /// notified of a [`glib::IOCondition::OUT`][crate::glib::IOCondition::OUT] condition. (On Windows in particular, this is
    /// very common due to the way the underlying APIs work.)
    ///
    /// The sum of the sizes of each #GOutputVector in vectors must not be
    /// greater than `G_MAXSSIZE`. If the message can be larger than this,
    /// then it is mandatory to use the g_socket_send_message_with_timeout()
    /// function.
    ///
    /// On error -1 is returned and @error is set accordingly.
    /// ## `address`
    /// a #GSocketAddress, or [`None`]
    /// ## `vectors`
    /// an array of #GOutputVector structs
    /// ## `messages`
    /// a pointer to an
    ///   array of #GSocketControlMessages, or [`None`].
    /// ## `flags`
    /// an int containing #GSocketMsgFlags flags, which may additionally
    ///    contain [other platform specific flags](http://man7.org/linux/man-pages/man2/recv.2.html)
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes written (which may be less than @size), or -1
    /// on error
    #[doc(alias = "g_socket_send_message")]
    fn send_message<P: IsA<SocketAddress>, C: IsA<Cancellable>>(
        &self,
        address: Option<&P>,
        vectors: &[OutputVector],
        messages: &[SocketControlMessage],
        flags: i32,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        unsafe {
            let mut error = ptr::null_mut();
            let ret = ffi::g_socket_send_message(
                self.as_ref().to_glib_none().0,
                address.map(|p| p.as_ref()).to_glib_none().0,
                vectors.as_ptr() as *mut ffi::GOutputVector,
                vectors.len().try_into().unwrap(),
                messages.as_ptr() as *mut _,
                messages.len().try_into().unwrap(),
                flags,
                cancellable.to_glib_none().0,
                &mut error,
            );
            if error.is_null() {
                Ok(ret as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// This behaves exactly the same as g_socket_send_message(), except that
    /// the choice of timeout behavior is determined by the @timeout_us argument
    /// rather than by @self's properties.
    ///
    /// On error [`PollableReturn::Failed`][crate::PollableReturn::Failed] is returned and @error is set accordingly, or
    /// if the socket is currently not writable [`PollableReturn::WouldBlock`][crate::PollableReturn::WouldBlock] is
    /// returned. @bytes_written will contain 0 in both cases.
    /// ## `address`
    /// a #GSocketAddress, or [`None`]
    /// ## `vectors`
    /// an array of #GOutputVector structs
    /// ## `messages`
    /// a pointer to an
    ///   array of #GSocketControlMessages, or [`None`].
    /// ## `flags`
    /// an int containing #GSocketMsgFlags flags, which may additionally
    ///    contain [other platform specific flags](http://man7.org/linux/man-pages/man2/recv.2.html)
    /// ## `timeout_us`
    /// the maximum time (in microseconds) to wait, or -1
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// [`PollableReturn::Ok`][crate::PollableReturn::Ok] if all data was successfully written,
    /// [`PollableReturn::WouldBlock`][crate::PollableReturn::WouldBlock] if the socket is currently not writable, or
    /// [`PollableReturn::Failed`][crate::PollableReturn::Failed] if an error happened and @error is set.
    ///
    /// ## `bytes_written`
    /// location to store the number of bytes that were written to the socket
    #[cfg(feature = "v2_60")]
    #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))]
    #[doc(alias = "g_socket_send_message_with_timeout")]
    fn send_message_with_timeout<P: IsA<SocketAddress>, C: IsA<Cancellable>>(
        &self,
        address: Option<&P>,
        vectors: &[OutputVector],
        messages: &[SocketControlMessage],
        flags: i32,
        timeout: Option<Duration>,
        cancellable: Option<&C>,
    ) -> Result<(PollableReturn, usize), glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        unsafe {
            let mut error = ptr::null_mut();
            let mut bytes_written = 0;

            let ret = ffi::g_socket_send_message_with_timeout(
                self.as_ref().to_glib_none().0,
                address.map(|p| p.as_ref()).to_glib_none().0,
                vectors.as_ptr() as *mut ffi::GOutputVector,
                vectors.len().try_into().unwrap(),
                messages.as_ptr() as *mut _,
                messages.len().try_into().unwrap(),
                flags,
                timeout
                    .map(|t| t.as_micros().try_into().unwrap())
                    .unwrap_or(-1),
                &mut bytes_written,
                cancellable.to_glib_none().0,
                &mut error,
            );
            if error.is_null() {
                Ok((from_glib(ret), bytes_written))
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// Send multiple data messages from @self in one go.  This is the most
    /// complicated and fully-featured version of this call. For easier use, see
    /// g_socket_send(), g_socket_send_to(), and g_socket_send_message().
    ///
    /// @messages must point to an array of #GOutputMessage structs and
    /// @num_messages must be the length of this array. Each #GOutputMessage
    /// contains an address to send the data to, and a pointer to an array of
    /// #GOutputVector structs to describe the buffers that the data to be sent
    /// for each message will be gathered from. Using multiple #GOutputVectors is
    /// more memory-efficient than manually copying data from multiple sources
    /// into a single buffer, and more network-efficient than making multiple
    /// calls to g_socket_send(). Sending multiple messages in one go avoids the
    /// overhead of making a lot of syscalls in scenarios where a lot of data
    /// packets need to be sent (e.g. high-bandwidth video streaming over RTP/UDP),
    /// or where the same data needs to be sent to multiple recipients.
    ///
    /// @flags modify how the message is sent. The commonly available arguments
    /// for this are available in the #GSocketMsgFlags enum, but the
    /// values there are the same as the system values, and the flags
    /// are passed in as-is, so you can pass in system-specific flags too.
    ///
    /// If the socket is in blocking mode the call will block until there is
    /// space for all the data in the socket queue. If there is no space available
    /// and the socket is in non-blocking mode a [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] error
    /// will be returned if no data was written at all, otherwise the number of
    /// messages sent will be returned. To be notified when space is available,
    /// wait for the [`glib::IOCondition::OUT`][crate::glib::IOCondition::OUT] condition. Note though that you may still receive
    /// [`IOErrorEnum::WouldBlock`][crate::IOErrorEnum::WouldBlock] from g_socket_send() even if you were previously
    /// notified of a [`glib::IOCondition::OUT`][crate::glib::IOCondition::OUT] condition. (On Windows in particular, this is
    /// very common due to the way the underlying APIs work.)
    ///
    /// On error -1 is returned and @error is set accordingly. An error will only
    /// be returned if zero messages could be sent; otherwise the number of messages
    /// successfully sent before the error will be returned.
    /// ## `messages`
    /// an array of #GOutputMessage structs
    /// ## `flags`
    /// an int containing #GSocketMsgFlags flags, which may additionally
    ///    contain [other platform specific flags](http://man7.org/linux/man-pages/man2/recv.2.html)
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// number of messages sent, or -1 on error. Note that the number of
    ///     messages sent may be smaller than @num_messages if the socket is
    ///     non-blocking or if @num_messages was larger than UIO_MAXIOV (1024),
    ///     in which case the caller may re-try to send the remaining messages.
    #[doc(alias = "g_socket_send_messages")]
    fn send_messages<C: IsA<Cancellable>>(
        &self,
        messages: &mut [OutputMessage],
        flags: i32,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        unsafe {
            let mut error = ptr::null_mut();
            let count = ffi::g_socket_send_messages(
                self.as_ref().to_glib_none().0,
                messages.as_mut_ptr() as *mut _,
                messages.len().try_into().unwrap(),
                flags,
                cancellable.to_glib_none().0,
                &mut error,
            );
            if error.is_null() {
                Ok(count as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// Tries to send @size bytes from @buffer to @address. If @address is
    /// [`None`] then the message is sent to the default receiver (set by
    /// g_socket_connect()).
    ///
    /// See g_socket_send() for additional information.
    /// ## `address`
    /// a #GSocketAddress, or [`None`]
    /// ## `buffer`
    /// the buffer
    ///     containing the data to send.
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes written (which may be less than @size), or -1
    /// on error
    #[doc(alias = "g_socket_send_to")]
    fn send_to<B: AsRef<[u8]>, P: IsA<SocketAddress>, C: IsA<Cancellable>>(
        &self,
        address: Option<&P>,
        buffer: B,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        let gcancellable = cancellable.to_glib_none();
        let (count, buffer_ptr) = {
            let slice = buffer.as_ref();
            (slice.len(), slice.as_ptr())
        };
        unsafe {
            let mut error = ptr::null_mut();

            let ret = ffi::g_socket_send_to(
                self.as_ref().to_glib_none().0,
                address.map(|p| p.as_ref()).to_glib_none().0,
                mut_override(buffer_ptr),
                count,
                gcancellable.0,
                &mut error,
            );
            if error.is_null() {
                Ok(ret as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }
    /// This behaves exactly the same as g_socket_send(), except that
    /// the choice of blocking or non-blocking behavior is determined by
    /// the @blocking argument rather than by @self's properties.
    /// ## `buffer`
    /// the buffer
    ///     containing the data to send.
    /// ## `blocking`
    /// whether to do blocking or non-blocking I/O
    /// ## `cancellable`
    /// a `GCancellable` or [`None`]
    ///
    /// # Returns
    ///
    /// Number of bytes written (which may be less than @size), or -1
    /// on error
    #[doc(alias = "g_socket_send_with_blocking")]
    fn send_with_blocking<B: AsRef<[u8]>, C: IsA<Cancellable>>(
        &self,
        buffer: B,
        blocking: bool,
        cancellable: Option<&C>,
    ) -> Result<usize, glib::Error> {
        let cancellable = cancellable.map(|c| c.as_ref());
        let gcancellable = cancellable.to_glib_none();
        let (count, buffer_ptr) = {
            let slice = buffer.as_ref();
            (slice.len(), slice.as_ptr())
        };
        unsafe {
            let mut error = ptr::null_mut();
            let ret = ffi::g_socket_send_with_blocking(
                self.as_ref().to_glib_none().0,
                mut_override(buffer_ptr),
                count,
                blocking.into_glib(),
                gcancellable.0,
                &mut error,
            );
            if error.is_null() {
                Ok(ret as usize)
            } else {
                Err(from_glib_full(error))
            }
        }
    }

    /// Returns the underlying OS socket object. On unix this
    /// is a socket file descriptor, and on Windows this is
    /// a Winsock2 SOCKET handle. This may be useful for
    /// doing platform specific or otherwise unusual operations
    /// on the socket.
    ///
    /// # Returns
    ///
    /// the file descriptor of the socket.
    #[cfg(unix)]
    #[cfg_attr(docsrs, doc(cfg(unix)))]
    #[doc(alias = "get_fd")]
    #[doc(alias = "g_socket_get_fd")]
    fn fd<T: FromRawFd>(&self) -> T {
        unsafe { FromRawFd::from_raw_fd(ffi::g_socket_get_fd(self.as_ref().to_glib_none().0)) }
    }

    #[cfg(windows)]
    #[cfg_attr(docsrs, doc(cfg(windows)))]
    #[doc(alias = "get_socket")]
    #[doc(alias = "g_socket_get_fd")]
    fn socket<T: FromRawSocket>(&self) -> T {
        unsafe {
            FromRawSocket::from_raw_socket(ffi::g_socket_get_fd(self.as_ref().to_glib_none().0) as _)
        }
    }

    #[doc(alias = "g_socket_create_source")]
    fn 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::ControlFlow + 'static,
        C: IsA<Cancellable>,
    {
        unsafe extern "C" fn trampoline<
            O: IsA<Socket>,
            F: FnMut(&O, glib::IOCondition) -> glib::ControlFlow + 'static,
        >(
            socket: *mut ffi::GSocket,
            condition: glib::ffi::GIOCondition,
            func: glib::ffi::gpointer,
        ) -> glib::ffi::gboolean {
            let func: &RefCell<F> = &*(func as *const RefCell<F>);
            let mut func = func.borrow_mut();
            (*func)(
                Socket::from_glib_borrow(socket).unsafe_cast_ref(),
                from_glib(condition),
            )
            .into_glib()
        }
        unsafe extern "C" fn destroy_closure<F>(ptr: glib::ffi::gpointer) {
            let _ = Box::<RefCell<F>>::from_raw(ptr as *mut _);
        }
        let cancellable = cancellable.map(|c| c.as_ref());
        let gcancellable = cancellable.to_glib_none();
        unsafe {
            let source = ffi::g_socket_create_source(
                self.as_ref().to_glib_none().0,
                condition.into_glib(),
                gcancellable.0,
            );
            let trampoline = trampoline::<Self, F> as glib::ffi::gpointer;
            glib::ffi::g_source_set_callback(
                source,
                Some(transmute::<
                    glib::ffi::gpointer,
                    unsafe extern "C" fn(glib::ffi::gpointer) -> glib::ffi::gboolean,
                >(trampoline)),
                Box::into_raw(Box::new(RefCell::new(func))) as glib::ffi::gpointer,
                Some(destroy_closure::<F>),
            );
            glib::ffi::g_source_set_priority(source, priority.into_glib());

            if let Some(name) = name {
                glib::ffi::g_source_set_name(source, name.to_glib_none().0);
            }

            from_glib_full(source)
        }
    }

    fn 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>> {
        let cancellable: Option<Cancellable> = cancellable.map(|c| c.as_ref()).cloned();

        let obj = self.clone();
        Box::pin(glib::SourceFuture::new(move |send| {
            let mut send = Some(send);
            obj.create_source(
                condition,
                cancellable.as_ref(),
                None,
                priority,
                move |_, condition| {
                    let _ = send.take().unwrap().send(condition);
                    glib::ControlFlow::Break
                },
            )
        }))
    }

    fn create_source_stream<C: IsA<Cancellable>>(
        &self,
        condition: glib::IOCondition,
        cancellable: Option<&C>,
        priority: glib::Priority,
    ) -> Pin<Box<dyn Stream<Item = glib::IOCondition> + 'static>> {
        let cancellable: Option<Cancellable> = cancellable.map(|c| c.as_ref()).cloned();

        let obj = self.clone();
        Box::pin(glib::SourceStream::new(move |send| {
            let send = Some(send);
            obj.create_source(
                condition,
                cancellable.as_ref(),
                None,
                priority,
                move |_, condition| {
                    if send.as_ref().unwrap().unbounded_send(condition).is_err() {
                        glib::ControlFlow::Break
                    } else {
                        glib::ControlFlow::Continue
                    }
                },
            )
        }))
    }
}

impl<O: IsA<Socket>> SocketExtManual for O {}

#[cfg(all(docsrs, not(unix)))]
pub trait IntoRawFd {
    fn into_raw_fd(self) -> libc::c_int;
}

#[cfg(all(docsrs, not(unix)))]
pub trait FromRawFd {
    unsafe fn from_raw_fd(fd: libc::c_int) -> Self;
}

#[cfg(all(docsrs, not(unix)))]
pub trait AsRawFd {
    fn as_raw_fd(&self) -> RawFd;
}

#[cfg(all(docsrs, not(unix)))]
pub type RawFd = libc::c_int;

#[cfg(all(docsrs, not(windows)))]
pub trait IntoRawSocket {
    fn into_raw_socket(self) -> u64;
}

#[cfg(all(docsrs, not(windows)))]
pub trait FromRawSocket {
    unsafe fn from_raw_socket(sock: u64) -> Self;
}

#[cfg(all(docsrs, not(windows)))]
pub trait AsRawSocket {
    fn as_raw_socket(&self) -> RawSocket;
}

#[cfg(all(docsrs, not(windows)))]
pub type RawSocket = *mut std::os::raw::c_void;

#[cfg(test)]
mod tests {
    #[test]
    #[cfg(unix)]
    fn socket_messages() {
        use std::{io, os::unix::io::AsRawFd};

        use super::Socket;
        use crate::{prelude::*, Cancellable, UnixFDMessage};

        let mut fds = [0 as libc::c_int; 2];
        let (out_sock, in_sock) = unsafe {
            let ret = libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr());
            if ret != 0 {
                panic!("{}", io::Error::last_os_error());
            }
            (
                Socket::from_fd(fds[0]).unwrap(),
                Socket::from_fd(fds[1]).unwrap(),
            )
        };

        let fd_msg = UnixFDMessage::new();
        fd_msg.append_fd(out_sock.as_raw_fd()).unwrap();
        let vs = [super::OutputVector::new(&[0])];
        let ctrl_msgs = [fd_msg.upcast()];
        let mut out_msg = [super::OutputMessage::new(
            crate::SocketAddress::NONE,
            vs.as_slice(),
            ctrl_msgs.as_slice(),
        )];
        let written = super::SocketExtManual::send_messages(
            &out_sock,
            out_msg.as_mut_slice(),
            0,
            Cancellable::NONE,
        )
        .unwrap();
        assert_eq!(written, 1);
        assert_eq!(out_msg[0].bytes_sent(), 1);

        let mut v = [0u8];
        let mut vs = [super::InputVector::new(v.as_mut_slice())];
        let mut ctrl_msgs = super::SocketControlMessages::new();
        let mut in_msg = [super::InputMessage::new(
            None,
            vs.as_mut_slice(),
            Some(&mut ctrl_msgs),
        )];
        let received = super::SocketExtManual::receive_messages(
            &in_sock,
            in_msg.as_mut_slice(),
            0,
            Cancellable::NONE,
        )
        .unwrap();

        assert_eq!(received, 1);
        assert_eq!(in_msg[0].bytes_received(), 1);
        assert_eq!(ctrl_msgs.len(), 1);
        let fds = ctrl_msgs[0]
            .downcast_ref::<UnixFDMessage>()
            .unwrap()
            .fd_list();
        assert_eq!(fds.length(), 1);
    }
    #[test]
    #[cfg(unix)]
    fn dgram_socket_messages() {
        use super::Socket;
        use crate::{prelude::*, Cancellable};

        let addr = crate::InetSocketAddress::from_string("127.0.0.1", 28351).unwrap();

        let out_sock = Socket::new(
            crate::SocketFamily::Ipv4,
            crate::SocketType::Datagram,
            crate::SocketProtocol::Udp,
        )
        .unwrap();
        let in_sock = Socket::new(
            crate::SocketFamily::Ipv4,
            crate::SocketType::Datagram,
            crate::SocketProtocol::Udp,
        )
        .unwrap();
        in_sock.bind(&addr, true).unwrap();

        const DATA: [u8; std::mem::size_of::<u64>()] = 1234u64.to_be_bytes();
        let out_vec = DATA;
        let out_vecs = [super::OutputVector::new(out_vec.as_slice())];
        let mut out_msg = [super::OutputMessage::new(
            Some(&addr),
            out_vecs.as_slice(),
            &[],
        )];
        let written = super::SocketExtManual::send_messages(
            &out_sock,
            out_msg.as_mut_slice(),
            0,
            Cancellable::NONE,
        )
        .unwrap();
        assert_eq!(written, 1);
        assert_eq!(out_msg[0].bytes_sent() as usize, out_vec.len());

        let mut in_addr = None;
        let mut in_vec = [0u8; DATA.len()];
        let mut in_vecs = [super::InputVector::new(in_vec.as_mut_slice())];
        let mut in_msg = [super::InputMessage::new(
            Some(&mut in_addr),
            in_vecs.as_mut_slice(),
            None,
        )];
        let received = super::SocketExtManual::receive_messages(
            &in_sock,
            in_msg.as_mut_slice(),
            0,
            Cancellable::NONE,
        )
        .unwrap();

        assert_eq!(received, 1);
        assert_eq!(in_msg[0].bytes_received(), in_vec.len());
        assert_eq!(in_vec, out_vec);
        let in_addr = in_addr
            .unwrap()
            .downcast::<crate::InetSocketAddress>()
            .unwrap();
        assert_eq!(in_addr.address().to_str(), addr.address().to_str());
    }
}