File: Types.hsc

package info (click to toggle)
haskell-network 3.2.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 760 kB
  • sloc: sh: 3,379; haskell: 2,211; ansic: 536; makefile: 3
file content (1447 lines) | stat: -rw-r--r-- 44,302 bytes parent folder | download
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
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash, UnboxedTuples #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

#include "HsNet.h"
##include "HsNetDef.h"

module Network.Socket.Types (
    -- * Socket type
      Socket
    , withFdSocket
    , unsafeFdSocket
    , touchSocket
    , socketToFd
    , fdSocket
    , mkSocket
    , invalidateSocket
    , close
    , close'
    , c_close
    -- * Types of socket
    , SocketType(GeneralSocketType, UnsupportedSocketType, NoSocketType
                , Stream, Datagram, Raw, RDM, SeqPacket)
    , isSupportedSocketType
    , packSocketType
    , unpackSocketType

    -- * Family
    , Family(GeneralFamily, UnsupportedFamily
            ,AF_UNSPEC,AF_UNIX,AF_INET,AF_INET6,AF_IMPLINK,AF_PUP,AF_CHAOS
            ,AF_NS,AF_NBS,AF_ECMA,AF_DATAKIT,AF_CCITT,AF_SNA,AF_DECnet
            ,AF_DLI,AF_LAT,AF_HYLINK,AF_APPLETALK,AF_ROUTE,AF_NETBIOS
            ,AF_NIT,AF_802,AF_ISO,AF_OSI,AF_NETMAN,AF_X25,AF_AX25,AF_OSINET
            ,AF_GOSSIP,AF_IPX,Pseudo_AF_XTP,AF_CTF,AF_WAN,AF_SDL,AF_NETWARE
            ,AF_NDD,AF_INTF,AF_COIP,AF_CNT,Pseudo_AF_RTIP,Pseudo_AF_PIP
            ,AF_SIP,AF_ISDN,Pseudo_AF_KEY,AF_NATM,AF_ARP,Pseudo_AF_HDRCMPLT
            ,AF_ENCAP,AF_LINK,AF_RAW,AF_RIF,AF_NETROM,AF_BRIDGE,AF_ATMPVC
            ,AF_ROSE,AF_NETBEUI,AF_SECURITY,AF_PACKET,AF_ASH,AF_ECONET
            ,AF_ATMSVC,AF_IRDA,AF_PPPOX,AF_WANPIPE,AF_BLUETOOTH,AF_CAN)
    , isSupportedFamily
    , packFamily
    , unpackFamily

    -- * Socket address typeclass
    , SocketAddress(..)
    , withSocketAddress
    , withNewSocketAddress

    -- * Socket address type
    , SockAddr(..)
    , isSupportedSockAddr
    , HostAddress
    , hostAddressToTuple
    , hostAddressToTuple'
    , tupleToHostAddress
    , HostAddress6
    , hostAddress6ToTuple
    , tupleToHostAddress6
    , FlowInfo
    , ScopeID
    , peekSockAddr
    , pokeSockAddr
    , withSockAddr

    -- * Null socket address type
    , NullSockAddr(..)

    -- * Unsorted
    , ProtocolNumber
    , defaultProtocol
    , PortNumber
    , defaultPort

    -- * Low-level helpers
    , zeroMemory
    , htonl
    , ntohl
    , In6Addr(..)
    ) where

import Data.IORef (IORef, newIORef, readIORef, atomicModifyIORef', mkWeakIORef)
import Foreign.C.Error (throwErrno)
import Foreign.Marshal.Alloc
import GHC.Conc (closeFdWith)
import System.Posix.Types (Fd)
import Control.DeepSeq (NFData (..))
import GHC.Exts (touch##)
import GHC.IORef (IORef (..))
import GHC.STRef (STRef (..))
import GHC.IO (IO (..))

import qualified Text.Read as P

import Foreign.Marshal.Array

import Network.Socket.Imports

----- readshow module import
import Network.Socket.ReadShow


-----------------------------------------------------------------------------

-- | Basic type for a socket.
data Socket = Socket (IORef CInt) CInt {- for Show -}

instance Show Socket where
    show (Socket _ ofd) = "<socket: " ++ show ofd ++ ">"

instance Eq Socket where
    Socket ref1 _ == Socket ref2 _ = ref1 == ref2

{-# DEPRECATED fdSocket "Use withFdSocket or unsafeFdSocket instead" #-}
-- | Currently, this is an alias of `unsafeFdSocket`.
fdSocket :: Socket -> IO CInt
fdSocket = unsafeFdSocket

-- | Getting a file descriptor from a socket.
--
--   If a 'Socket' is shared with multiple threads and
--   one uses 'unsafeFdSocket', unexpected issues may happen.
--   Consider the following scenario:
--
--   1) Thread A acquires a 'Fd' from 'Socket' by 'unsafeFdSocket'.
--
--   2) Thread B close the 'Socket'.
--
--   3) Thread C opens a new 'Socket'. Unfortunately it gets the same 'Fd'
--      number which thread A is holding.
--
--   In this case, it is safer for Thread A to clone 'Fd' by
--   'System.Posix.IO.dup'. But this would still suffer from
--   a race condition between 'unsafeFdSocket' and 'close'.
--
--   If you use this function, you need to guarantee that the 'Socket' does not
--   get garbage-collected until after you finish using the file descriptor.
--   'touchSocket' can be used for this purpose.
--
--   A safer option is to use 'withFdSocket' instead.
unsafeFdSocket :: Socket -> IO CInt
unsafeFdSocket (Socket ref _) = readIORef ref

-- | Ensure that the given 'Socket' stays alive (i.e. not garbage-collected)
--   at the given place in the sequence of IO actions. This function can be
--   used in conjunction with 'unsafeFdSocket' to guarantee that the file
--   descriptor is not prematurely freed.
--
-- > fd <- unsafeFdSocket sock
-- > -- using fd with blocking operations such as accept(2)
-- > touchSocket sock
touchSocket :: Socket -> IO ()
touchSocket (Socket ref _) = touch ref

touch :: IORef a -> IO ()
touch (IORef (STRef mutVar)) =
  -- Thanks to a GHC issue, this touch# may not be quite guaranteed
  -- to work. There's talk of replacing the touch# primop with one
  -- that works better with the optimizer. But this seems to be the
  -- "right" way to do it for now.
  IO $ \s -> (## touch## mutVar s, () ##)

-- | Get a file descriptor from a 'Socket'. The socket will never
-- be closed automatically before @withFdSocket@ completes, but
-- it may still be closed by an explicit call to 'close' or `close'`,
-- either before or during the call.
--
-- The file descriptor must not be used after @withFdSocket@ returns, because
-- the 'Socket' may have been garbage-collected, invalidating the file
-- descriptor.
--
-- Since: 3.1.0.0
withFdSocket :: Socket -> (CInt -> IO r) -> IO r
withFdSocket (Socket ref _) f = do
  fd <- readIORef ref
  -- Should we throw an exception if the socket is already invalid?
  -- That will catch some mistakes but certainly not all.

  r <- f fd

  touch ref
  return r

-- | Socket is closed and a duplicated file descriptor is returned.
--   The duplicated descriptor is no longer subject to the possibility
--   of unexpectedly being closed if the socket is finalized. It is
--   now the caller's responsibility to ultimately close the
--   duplicated file descriptor.
socketToFd :: Socket -> IO CInt
socketToFd s = do
#if defined(mingw32_HOST_OS)
    fd <- unsafeFdSocket s
    fd2 <- c_wsaDuplicate fd
    -- FIXME: throw error no if -1
    close s
    return fd2

foreign import ccall unsafe "wsaDuplicate"
   c_wsaDuplicate :: CInt -> IO CInt
#else
    fd <- unsafeFdSocket s
    -- FIXME: throw error no if -1
    fd2 <- c_dup fd
    close s
    return fd2

foreign import ccall unsafe "dup"
   c_dup :: CInt -> IO CInt
#endif

-- | Creating a socket from a file descriptor.
mkSocket :: CInt -> IO Socket
mkSocket fd = do
    ref <- newIORef fd
    let s = Socket ref fd
    void $ mkWeakIORef ref $ close s
    return s

invalidSocket :: CInt
#if defined(mingw32_HOST_OS)
invalidSocket = #const INVALID_SOCKET
#else
invalidSocket = -1
#endif

invalidateSocket ::
      Socket
   -> (CInt -> IO a)
   -> (CInt -> IO a)
   -> IO a
invalidateSocket (Socket ref _) errorAction normalAction = do
    oldfd <- atomicModifyIORef' ref $ \cur -> (invalidSocket, cur)
    if oldfd == invalidSocket then errorAction oldfd else normalAction oldfd

-----------------------------------------------------------------------------

-- | Close the socket. This function does not throw exceptions even if
--   the underlying system call returns errors.
--
--   If multiple threads use the same socket and one uses 'unsafeFdSocket' and
--   the other use 'close', unexpected behavior may happen.
--   For more information, please refer to the documentation of 'unsafeFdSocket'.
close :: Socket -> IO ()
close s = invalidateSocket s (\_ -> return ()) $ \oldfd -> do
    -- closeFdWith avoids the deadlock of IO manager.
    closeFdWith closeFd (toFd oldfd)
  where
    toFd :: CInt -> Fd
    toFd = fromIntegral
    -- closeFd ignores the return value of c_close and
    -- does not throw exceptions
    closeFd :: Fd -> IO ()
    closeFd = void . c_close . fromIntegral

-- | Close the socket. This function throws exceptions if
--   the underlying system call returns errors.
close' :: Socket -> IO ()
close' s = invalidateSocket s (\_ -> return ()) $ \oldfd -> do
    -- closeFdWith avoids the deadlock of IO manager.
    closeFdWith closeFd (toFd oldfd)
  where
    toFd :: CInt -> Fd
    toFd = fromIntegral
    closeFd :: Fd -> IO ()
    closeFd fd = do
        ret <- c_close $ fromIntegral fd
        when (ret == -1) $ throwErrno "Network.Socket.close'"

#if defined(mingw32_HOST_OS)
foreign import CALLCONV unsafe "closesocket"
  c_close :: CInt -> IO CInt
#else
foreign import ccall unsafe "close"
  c_close :: CInt -> IO CInt
#endif

-----------------------------------------------------------------------------

-- | Protocol number.
type ProtocolNumber = CInt

-- | This is the default protocol for a given service.
--
-- >>> defaultProtocol
-- 0
defaultProtocol :: ProtocolNumber
defaultProtocol = 0

-----------------------------------------------------------------------------
-- Socket types

-- There are a few possible ways to do this.  The first is convert the
-- structs used in the C library into an equivalent Haskell type. An
-- other possible implementation is to keep all the internals in the C
-- code and use an Int## and a status flag. The second method is used
-- here since a lot of the C structures are not required to be
-- manipulated.

-- Originally the status was non-mutable so we had to return a new
-- socket each time we changed the status.  This version now uses
-- mutable variables to avoid the need to do this.  The result is a
-- cleaner interface and better security since the application
-- programmer now can't circumvent the status information to perform
-- invalid operations on sockets.

-- | Socket Types.
--
-- Some of the defined patterns may be unsupported on some systems:
-- see 'isSupportedSocketType'.
newtype SocketType = SocketType { packSocketType :: CInt }
        deriving (Eq, Ord)

unpackSocketType :: CInt -> SocketType
unpackSocketType = SocketType
{-# INLINE unpackSocketType #-}

-- | Is the @SOCK_xxxxx@ constant corresponding to the given SocketType known
-- on this system?  'GeneralSocketType' values, not equal to any of the named
-- patterns or 'UnsupportedSocketType', will return 'True' even when not
-- known on this system.
isSupportedSocketType :: SocketType -> Bool
isSupportedSocketType = (/= UnsupportedSocketType)

-- | Pattern for a general socket type.
pattern GeneralSocketType    :: CInt -> SocketType
pattern GeneralSocketType n  =  SocketType n
#if __GLASGOW_HASKELL__ >= 806
{-# COMPLETE GeneralSocketType #-}
#endif
-- The actual constructor is not exported, which keeps the internal
-- representation private, but for all purposes other than 'coerce' the
-- above pattern is just as good.

-- | Unsupported socket type, equal to any other types not supported on this
-- system.
pattern UnsupportedSocketType :: SocketType
pattern UnsupportedSocketType  = SocketType (-1)

-- | Used in getAddrInfo hints, for example.
pattern NoSocketType        :: SocketType
pattern NoSocketType         = SocketType 0

pattern Stream              :: SocketType
#ifdef SOCK_STREAM
pattern Stream               = SocketType (#const SOCK_STREAM)
#else
pattern Stream               = UnsupportedSocketType
#endif

pattern Datagram            :: SocketType
#ifdef SOCK_DGRAM
pattern Datagram             = SocketType (#const SOCK_DGRAM)
#else
pattern Datagram             = UnsupportedSocketType
#endif

pattern Raw                 :: SocketType
#ifdef SOCK_RAW
pattern Raw                  = SocketType (#const SOCK_RAW)
#else
pattern Raw                  = UnsupportedSocketType
#endif

pattern RDM                 :: SocketType
#ifdef SOCK_RDM
pattern RDM                  = SocketType (#const SOCK_RDM)
#else
pattern RDM                  = UnsupportedSocketType
#endif

pattern SeqPacket           :: SocketType
#ifdef SOCK_SEQPACKET
pattern SeqPacket            = SocketType (#const SOCK_SEQPACKET)
#else
pattern SeqPacket            = UnsupportedSocketType
#endif

------------------------------------------------------------------------
-- Protocol Families.


-- | Address families.  The @AF_xxxxx@ constants are widely used as synonyms
-- for the corresponding @PF_xxxxx@ protocol family values, to which they are
-- numerically equal in mainstream socket API implementations.
--
-- Strictly correct usage would be to pass the @PF_xxxxx@ constants as the first
-- argument when creating a 'Socket', while the @AF_xxxxx@ constants should be
-- used as @addrFamily@ values with 'getAddrInfo'.  For now only the @AF_xxxxx@
-- constants are provided.
--
-- Some of the defined patterns may be unsupported on some systems:
-- see 'isSupportedFamily'.
newtype Family = Family { packFamily :: CInt } deriving (Eq, Ord)


-- | Does one of the AF_ constants correspond to a known address family on this
-- system.  'GeneralFamily' values, not equal to any of the named @AF_xxxxx@
-- patterns or 'UnsupportedFamily', will return 'True' even when not known on
-- this system.
isSupportedFamily :: Family -> Bool
isSupportedFamily f = case f of
    UnsupportedFamily -> False
    GeneralFamily _   -> True

-- | Convert 'CInt' to 'Family'.
unpackFamily :: CInt -> Family
unpackFamily = Family
{-# INLINE unpackFamily #-}

-- | Pattern for a general protocol family (a.k.a. address family).
--
-- @since 3.2.0.0
pattern GeneralFamily      :: CInt -> Family
pattern GeneralFamily n     = Family n
#if __GLASGOW_HASKELL__ >= 806
{-# COMPLETE GeneralFamily #-}
#endif
-- The actual constructor is not exported, which keeps the internal
-- representation private, but for all purposes other than 'coerce' the
-- above pattern is just as good.

-- | Unsupported address family, equal to any other families that are not
-- supported on the system.
--
-- @since 3.2.0.0
pattern UnsupportedFamily  :: Family
pattern UnsupportedFamily   = Family (-1)

-- | unspecified
pattern AF_UNSPEC          :: Family
pattern AF_UNSPEC           = Family (#const AF_UNSPEC)

-- | UNIX-domain
pattern AF_UNIX            :: Family
#ifdef AF_UNIX
pattern AF_UNIX             = Family (#const AF_UNIX)
#else
pattern AF_UNIX             = Family (-1)
#endif

-- | Internet Protocol version 4
pattern AF_INET            :: Family
#ifdef AF_INET
pattern AF_INET             = Family (#const AF_INET)
#else
pattern AF_INET             = Family (-1)
#endif

-- | Internet Protocol version 6
pattern AF_INET6           :: Family
#ifdef AF_INET6
pattern AF_INET6            = Family (#const AF_INET6)
#else
pattern AF_INET6            = Family (-1)
#endif

-- | Arpanet imp addresses
pattern AF_IMPLINK         :: Family
#ifdef AF_IMPLINK
pattern AF_IMPLINK          = Family (#const AF_IMPLINK)
#else
pattern AF_IMPLINK          = Family (-1)
#endif

-- | pup protocols: e.g. BSP
pattern AF_PUP             :: Family
#ifdef AF_PUP
pattern AF_PUP              = Family (#const AF_PUP)
#else
pattern AF_PUP              = Family (-1)
#endif

-- | mit CHAOS protocols
pattern AF_CHAOS           :: Family
#ifdef AF_CHAOS
pattern AF_CHAOS            = Family (#const AF_CHAOS)
#else
pattern AF_CHAOS            = Family (-1)
#endif

-- | XEROX NS protocols
pattern AF_NS              :: Family
#ifdef AF_NS
pattern AF_NS               = Family (#const AF_NS)
#else
pattern AF_NS               = Family (-1)
#endif

-- | nbs protocols
pattern AF_NBS             :: Family
#ifdef AF_NBS
pattern AF_NBS              = Family (#const AF_NBS)
#else
pattern AF_NBS              = Family (-1)
#endif

-- | european computer manufacturers
pattern AF_ECMA            :: Family
#ifdef AF_ECMA
pattern AF_ECMA             = Family (#const AF_ECMA)
#else
pattern AF_ECMA             = Family (-1)
#endif

-- | datakit protocols
pattern AF_DATAKIT         :: Family
#ifdef AF_DATAKIT
pattern AF_DATAKIT          = Family (#const AF_DATAKIT)
#else
pattern AF_DATAKIT          = Family (-1)
#endif

-- | CCITT protocols, X.25 etc
pattern AF_CCITT           :: Family
#ifdef AF_CCITT
pattern AF_CCITT            = Family (#const AF_CCITT)
#else
pattern AF_CCITT            = Family (-1)
#endif

-- | IBM SNA
pattern AF_SNA             :: Family
#ifdef AF_SNA
pattern AF_SNA              = Family (#const AF_SNA)
#else
pattern AF_SNA              = Family (-1)
#endif

-- | DECnet
pattern AF_DECnet          :: Family
#ifdef AF_DECnet
pattern AF_DECnet           = Family (#const AF_DECnet)
#else
pattern AF_DECnet           = Family (-1)
#endif

-- | Direct data link interface
pattern AF_DLI             :: Family
#ifdef AF_DLI
pattern AF_DLI              = Family (#const AF_DLI)
#else
pattern AF_DLI              = Family (-1)
#endif

-- | LAT
pattern AF_LAT             :: Family
#ifdef AF_LAT
pattern AF_LAT              = Family (#const AF_LAT)
#else
pattern AF_LAT              = Family (-1)
#endif

-- | NSC Hyperchannel
pattern AF_HYLINK          :: Family
#ifdef AF_HYLINK
pattern AF_HYLINK           = Family (#const AF_HYLINK)
#else
pattern AF_HYLINK           = Family (-1)
#endif

-- | Apple Talk
pattern AF_APPLETALK       :: Family
#ifdef AF_APPLETALK
pattern AF_APPLETALK        = Family (#const AF_APPLETALK)
#else
pattern AF_APPLETALK        = Family (-1)
#endif

-- | Internal Routing Protocol (aka AF_NETLINK)
pattern AF_ROUTE           :: Family
#ifdef AF_ROUTE
pattern AF_ROUTE            = Family (#const AF_ROUTE)
#else
pattern AF_ROUTE            = Family (-1)
#endif

-- | NetBios-style addresses
pattern AF_NETBIOS         :: Family
#ifdef AF_NETBIOS
pattern AF_NETBIOS          = Family (#const AF_NETBIOS)
#else
pattern AF_NETBIOS          = Family (-1)
#endif

-- | Network Interface Tap
pattern AF_NIT             :: Family
#ifdef AF_NIT
pattern AF_NIT              = Family (#const AF_NIT)
#else
pattern AF_NIT              = Family (-1)
#endif

-- | IEEE 802.2, also ISO 8802
pattern AF_802             :: Family
#ifdef AF_802
pattern AF_802              = Family (#const AF_802)
#else
pattern AF_802              = Family (-1)
#endif

-- | ISO protocols
pattern AF_ISO             :: Family
#ifdef AF_ISO
pattern AF_ISO              = Family (#const AF_ISO)
#else
pattern AF_ISO              = Family (-1)
#endif

-- | umbrella of all families used by OSI
pattern AF_OSI             :: Family
#ifdef AF_OSI
pattern AF_OSI              = Family (#const AF_OSI)
#else
pattern AF_OSI              = Family (-1)
#endif

-- | DNA Network Management
pattern AF_NETMAN          :: Family
#ifdef AF_NETMAN
pattern AF_NETMAN           = Family (#const AF_NETMAN)
#else
pattern AF_NETMAN           = Family (-1)
#endif

-- | CCITT X.25
pattern AF_X25             :: Family
#ifdef AF_X25
pattern AF_X25              = Family (#const AF_X25)
#else
pattern AF_X25              = Family (-1)
#endif

-- | AX25
pattern AF_AX25            :: Family
#ifdef AF_AX25
pattern AF_AX25             = Family (#const AF_AX25)
#else
pattern AF_AX25             = Family (-1)
#endif

-- | AFI
pattern AF_OSINET          :: Family
#ifdef AF_OSINET
pattern AF_OSINET           = Family (#const AF_OSINET)
#else
pattern AF_OSINET           = Family (-1)
#endif

-- | US Government OSI
pattern AF_GOSSIP          :: Family
#ifdef AF_GOSSIP
pattern AF_GOSSIP           = Family (#const AF_GOSSIP)
#else
pattern AF_GOSSIP           = Family (-1)
#endif

-- | Novell Internet Protocol
pattern AF_IPX             :: Family
#ifdef AF_IPX
pattern AF_IPX              = Family (#const AF_IPX)
#else
pattern AF_IPX              = Family (-1)
#endif

-- | eXpress Transfer Protocol (no AF)
pattern Pseudo_AF_XTP      :: Family
#ifdef Pseudo_AF_XTP
pattern Pseudo_AF_XTP       = Family (#const Pseudo_AF_XTP)
#else
pattern Pseudo_AF_XTP       = Family (-1)
#endif

-- | Common Trace Facility
pattern AF_CTF             :: Family
#ifdef AF_CTF
pattern AF_CTF              = Family (#const AF_CTF)
#else
pattern AF_CTF              = Family (-1)
#endif

-- | Wide Area Network protocols
pattern AF_WAN             :: Family
#ifdef AF_WAN
pattern AF_WAN              = Family (#const AF_WAN)
#else
pattern AF_WAN              = Family (-1)
#endif

-- | SGI Data Link for DLPI
pattern AF_SDL             :: Family
#ifdef AF_SDL
pattern AF_SDL              = Family (#const AF_SDL)
#else
pattern AF_SDL              = Family (-1)
#endif

-- | Netware
pattern AF_NETWARE         :: Family
#ifdef AF_NETWARE
pattern AF_NETWARE          = Family (#const AF_NETWARE)
#else
pattern AF_NETWARE          = Family (-1)
#endif

-- | NDD
pattern AF_NDD             :: Family
#ifdef AF_NDD
pattern AF_NDD              = Family (#const AF_NDD)
#else
pattern AF_NDD              = Family (-1)
#endif

-- | Debugging use only
pattern AF_INTF            :: Family
#ifdef AF_INTF
pattern AF_INTF             = Family (#const AF_INTF)
#else
pattern AF_INTF             = Family (-1)
#endif

-- | connection-oriented IP, aka ST II
pattern AF_COIP            :: Family
#ifdef AF_COIP
pattern AF_COIP             = Family (#const AF_COIP)
#else
pattern AF_COIP             = Family (-1)
#endif

-- | Computer Network Technology
pattern AF_CNT             :: Family
#ifdef AF_CNT
pattern AF_CNT              = Family (#const AF_CNT)
#else
pattern AF_CNT              = Family (-1)
#endif

-- | Help Identify RTIP packets
pattern Pseudo_AF_RTIP     :: Family
#ifdef Pseudo_AF_RTIP
pattern Pseudo_AF_RTIP      = Family (#const Pseudo_AF_RTIP)
#else
pattern Pseudo_AF_RTIP      = Family (-1)
#endif

-- | Help Identify PIP packets
pattern Pseudo_AF_PIP      :: Family
#ifdef Pseudo_AF_PIP
pattern Pseudo_AF_PIP       = Family (#const Pseudo_AF_PIP)
#else
pattern Pseudo_AF_PIP       = Family (-1)
#endif

-- | Simple Internet Protocol
pattern AF_SIP             :: Family
#ifdef AF_SIP
pattern AF_SIP              = Family (#const AF_SIP)
#else
pattern AF_SIP              = Family (-1)
#endif

-- | Integrated Services Digital Network
pattern AF_ISDN            :: Family
#ifdef AF_ISDN
pattern AF_ISDN             = Family (#const AF_ISDN)
#else
pattern AF_ISDN             = Family (-1)
#endif

-- | Internal key-management function
pattern Pseudo_AF_KEY      :: Family
#ifdef Pseudo_AF_KEY
pattern Pseudo_AF_KEY       = Family (#const Pseudo_AF_KEY)
#else
pattern Pseudo_AF_KEY       = Family (-1)
#endif

-- | native ATM access
pattern AF_NATM            :: Family
#ifdef AF_NATM
pattern AF_NATM             = Family (#const AF_NATM)
#else
pattern AF_NATM             = Family (-1)
#endif

-- | ARP (RFC 826)
pattern AF_ARP             :: Family
#ifdef AF_ARP
pattern AF_ARP              = Family (#const AF_ARP)
#else
pattern AF_ARP              = Family (-1)
#endif

-- | Used by BPF to not rewrite hdrs in iface output
pattern Pseudo_AF_HDRCMPLT :: Family
#ifdef Pseudo_AF_HDRCMPLT
pattern Pseudo_AF_HDRCMPLT  = Family (#const Pseudo_AF_HDRCMPLT)
#else
pattern Pseudo_AF_HDRCMPLT  = Family (-1)
#endif

-- | ENCAP
pattern AF_ENCAP           :: Family
#ifdef AF_ENCAP
pattern AF_ENCAP            = Family (#const AF_ENCAP)
#else
pattern AF_ENCAP            = Family (-1)
#endif

-- | Link layer interface
pattern AF_LINK            :: Family
#ifdef AF_LINK
pattern AF_LINK             = Family (#const AF_LINK)
#else
pattern AF_LINK             = Family (-1)
#endif

-- | Link layer interface
pattern AF_RAW             :: Family
#ifdef AF_RAW
pattern AF_RAW              = Family (#const AF_RAW)
#else
pattern AF_RAW              = Family (-1)
#endif

-- | raw interface
pattern AF_RIF             :: Family
#ifdef AF_RIF
pattern AF_RIF              = Family (#const AF_RIF)
#else
pattern AF_RIF              = Family (-1)
#endif

-- | Amateur radio NetROM
pattern AF_NETROM          :: Family
#ifdef AF_NETROM
pattern AF_NETROM           = Family (#const AF_NETROM)
#else
pattern AF_NETROM           = Family (-1)
#endif

-- | multiprotocol bridge
pattern AF_BRIDGE          :: Family
#ifdef AF_BRIDGE
pattern AF_BRIDGE           = Family (#const AF_BRIDGE)
#else
pattern AF_BRIDGE           = Family (-1)
#endif

-- | ATM PVCs
pattern AF_ATMPVC          :: Family
#ifdef AF_ATMPVC
pattern AF_ATMPVC           = Family (#const AF_ATMPVC)
#else
pattern AF_ATMPVC           = Family (-1)
#endif

-- | Amateur Radio X.25 PLP
pattern AF_ROSE            :: Family
#ifdef AF_ROSE
pattern AF_ROSE             = Family (#const AF_ROSE)
#else
pattern AF_ROSE             = Family (-1)
#endif

-- | Netbeui 802.2LLC
pattern AF_NETBEUI         :: Family
#ifdef AF_NETBEUI
pattern AF_NETBEUI          = Family (#const AF_NETBEUI)
#else
pattern AF_NETBEUI          = Family (-1)
#endif

-- | Security callback pseudo AF
pattern AF_SECURITY        :: Family
#ifdef AF_SECURITY
pattern AF_SECURITY         = Family (#const AF_SECURITY)
#else
pattern AF_SECURITY         = Family (-1)
#endif

-- | Packet family
pattern AF_PACKET          :: Family
#ifdef AF_PACKET
pattern AF_PACKET           = Family (#const AF_PACKET)
#else
pattern AF_PACKET           = Family (-1)
#endif

-- | Ash
pattern AF_ASH             :: Family
#ifdef AF_ASH
pattern AF_ASH              = Family (#const AF_ASH)
#else
pattern AF_ASH              = Family (-1)
#endif

-- | Acorn Econet
pattern AF_ECONET          :: Family
#ifdef AF_ECONET
pattern AF_ECONET           = Family (#const AF_ECONET)
#else
pattern AF_ECONET           = Family (-1)
#endif

-- | ATM SVCs
pattern AF_ATMSVC          :: Family
#ifdef AF_ATMSVC
pattern AF_ATMSVC           = Family (#const AF_ATMSVC)
#else
pattern AF_ATMSVC           = Family (-1)
#endif

-- | IRDA sockets
pattern AF_IRDA            :: Family
#ifdef AF_IRDA
pattern AF_IRDA             = Family (#const AF_IRDA)
#else
pattern AF_IRDA             = Family (-1)
#endif

-- | PPPoX sockets
pattern AF_PPPOX           :: Family
#ifdef AF_PPPOX
pattern AF_PPPOX            = Family (#const AF_PPPOX)
#else
pattern AF_PPPOX            = Family (-1)
#endif

-- | Wanpipe API sockets
pattern AF_WANPIPE         :: Family
#ifdef AF_WANPIPE
pattern AF_WANPIPE          = Family (#const AF_WANPIPE)
#else
pattern AF_WANPIPE          = Family (-1)
#endif

-- | bluetooth sockets
pattern AF_BLUETOOTH       :: Family
#ifdef AF_BLUETOOTH
pattern AF_BLUETOOTH        = Family (#const AF_BLUETOOTH)
#else
pattern AF_BLUETOOTH        = Family (-1)
#endif

-- | Controller Area Network
pattern AF_CAN             :: Family
#ifdef AF_CAN
pattern AF_CAN              = Family (#const AF_CAN)
#else
pattern AF_CAN              = Family (-1)
#endif

------------------------------------------------------------------------
-- Port Numbers

-- | Port number.
--   Use the @Num@ instance (i.e. use a literal) to create a
--   @PortNumber@ value.
--
-- >>> 1 :: PortNumber
-- 1
-- >>> read "1" :: PortNumber
-- 1
-- >>> show (12345 :: PortNumber)
-- "12345"
-- >>> 50000 < (51000 :: PortNumber)
-- True
-- >>> 50000 < (52000 :: PortNumber)
-- True
-- >>> 50000 + (10000 :: PortNumber)
-- 60000
newtype PortNumber = PortNum Word16 deriving (Eq, Ord, Num, Enum, Bounded, Real, Integral)

foreign import CALLCONV unsafe "ntohs" ntohs :: Word16 -> Word16
foreign import CALLCONV unsafe "htons" htons :: Word16 -> Word16
-- | Converts the from host byte order to network byte order.
foreign import CALLCONV unsafe "htonl" htonl :: Word32 -> Word32
-- | Converts the from network byte order to host byte order.
foreign import CALLCONV unsafe "ntohl" ntohl :: Word32 -> Word32
{-# DEPRECATED htonl "Use getAddrInfo instead" #-}
{-# DEPRECATED ntohl "Use getAddrInfo instead" #-}

instance Storable PortNumber where
   sizeOf    ~_ = sizeOf    (0 :: Word16)
   alignment ~_ = alignment (0 :: Word16)
   poke p (PortNum po) = poke (castPtr p) (htons po)
   peek p = PortNum . ntohs <$> peek (castPtr p)

-- | Default port number.
--
-- >>> defaultPort
-- 0
defaultPort :: PortNumber
defaultPort = 0

------------------------------------------------------------------------

-- | The core typeclass to unify socket addresses.
class SocketAddress sa where
    sizeOfSocketAddress :: sa -> Int
    peekSocketAddress :: Ptr sa -> IO sa
    pokeSocketAddress  :: Ptr a -> sa -> IO ()

-- sizeof(struct sockaddr_storage) which has enough space to contain
-- sockaddr_in, sockaddr_in6 and sockaddr_un.
sockaddrStorageLen :: Int
sockaddrStorageLen = 128

{-# NOINLINE withSocketAddress #-}
withSocketAddress :: SocketAddress sa => sa -> (Ptr sa -> Int -> IO a) -> IO a
withSocketAddress addr f = do
    let sz = sizeOfSocketAddress addr
    if sz == 0 then
        f nullPtr 0
      else
        allocaBytes sz $ \p -> pokeSocketAddress p addr >> f (castPtr p) sz

withNewSocketAddress :: SocketAddress sa => (Ptr sa -> Int -> IO a) -> IO a
withNewSocketAddress f = allocaBytes sockaddrStorageLen $ \ptr -> do
    zeroMemory ptr $ fromIntegral sockaddrStorageLen
    f ptr sockaddrStorageLen

------------------------------------------------------------------------

-- | A null 'SocketAddress' for situations where a socket address
--   parameter is optional.
data NullSockAddr = NullSockAddr

instance SocketAddress NullSockAddr where
    sizeOfSocketAddress _ = 0
    peekSocketAddress _   = return NullSockAddr
    pokeSocketAddress _ _ = return ()

------------------------------------------------------------------------
-- Socket addresses

-- The scheme used for addressing sockets is somewhat quirky. The
-- calls in the BSD socket API that need to know the socket address
-- all operate in terms of struct sockaddr, a `virtual' type of
-- socket address.

-- The Internet family of sockets are addressed as struct sockaddr_in,
-- so when calling functions that operate on struct sockaddr, we have
-- to type cast the Internet socket address into a struct sockaddr.
-- Instances of the structure for different families might *not* be
-- the same size. Same casting is required of other families of
-- sockets such as Xerox NS. Similarly for UNIX-domain sockets.

-- To represent these socket addresses in Haskell-land, we do what BSD
-- didn't do, and use a union/algebraic type for the different
-- families. Currently only UNIX-domain sockets and the Internet
-- families are supported.

-- | Flow information.
type FlowInfo = Word32
-- | Scope identifier.
type ScopeID = Word32

-- | Socket addresses.
--  The existence of a constructor does not necessarily imply that
--  that socket address type is supported on your system: see
-- 'isSupportedSockAddr'.
data SockAddr
  = SockAddrInet
        PortNumber      -- sin_port
        HostAddress     -- sin_addr  (ditto)
  | SockAddrInet6
        PortNumber      -- sin6_port
        FlowInfo        -- sin6_flowinfo (ditto)
        HostAddress6    -- sin6_addr (ditto)
        ScopeID         -- sin6_scope_id (ditto)
  -- | The path must have fewer than 104 characters. All of these characters must have code points less than 256.
  | SockAddrUnix
        String           -- sun_path
  deriving (Eq, Ord)

instance NFData SockAddr where
  rnf (SockAddrInet _ _) = ()
  rnf (SockAddrInet6 _ _ _ _) = ()
  rnf (SockAddrUnix str) = rnf str

-- | Is the socket address type supported on this system?
isSupportedSockAddr :: SockAddr -> Bool
isSupportedSockAddr addr = case addr of
  SockAddrInet{}  -> True
  SockAddrInet6{} -> True
  SockAddrUnix{}  -> True

instance SocketAddress SockAddr where
    sizeOfSocketAddress = sizeOfSockAddr
    peekSocketAddress   = peekSockAddr
    pokeSocketAddress   = pokeSockAddr

#if defined(mingw32_HOST_OS)
type CSaFamily = (#type unsigned short)
#elif defined(darwin_HOST_OS)
type CSaFamily = (#type u_char)
#else
type CSaFamily = (#type sa_family_t)
#endif

-- | Computes the storage requirements (in bytes) of the given
-- 'SockAddr'.  This function differs from 'Foreign.Storable.sizeOf'
-- in that the value of the argument /is/ used.
sizeOfSockAddr :: SockAddr -> Int
# ifdef linux_HOST_OS
-- http://man7.org/linux/man-pages/man7/unix.7.html says:
-- "an abstract socket address is distinguished (from a
-- pathname socket) by the fact that sun_path[0] is a null byte
-- ('\0').  The socket's address in this namespace is given by the
-- additional bytes in sun_path that are covered by the specified
-- length of the address structure.  (Null bytes in the name have no
-- special significance.)  The name has no connection with filesystem
-- pathnames.  When the address of an abstract socket is returned,
-- the returned addrlen is greater than sizeof(sa_family_t) (i.e.,
-- greater than 2), and the name of the socket is contained in the
-- first (addrlen - sizeof(sa_family_t)) bytes of sun_path."
sizeOfSockAddr (SockAddrUnix path) =
    case path of
        '\0':_ -> (#const sizeof(sa_family_t)) + length path
        _      -> #const sizeof(struct sockaddr_un)
# else
sizeOfSockAddr SockAddrUnix{}  = #const sizeof(struct sockaddr_un)
# endif
sizeOfSockAddr SockAddrInet{}  = #const sizeof(struct sockaddr_in)
sizeOfSockAddr SockAddrInet6{} = #const sizeof(struct sockaddr_in6)

-- The combination of "-XString" and inlining results in a bug where
-- "sz" is always 0.
{-# NOINLINE withSockAddr #-}
-- | Use a 'SockAddr' with a function requiring a pointer to a
-- 'SockAddr' and the length of that 'SockAddr'.
withSockAddr :: SockAddr -> (Ptr SockAddr -> Int -> IO a) -> IO a
withSockAddr addr f = do
    let sz = sizeOfSockAddr addr
    allocaBytes sz $ \p -> pokeSockAddr p addr >> f (castPtr p) sz

-- We cannot bind sun_paths longer than than the space in the sockaddr_un
-- structure, and attempting to do so could overflow the allocated storage
-- space.  This constant holds the maximum allowable path length.
--
unixPathMax :: Int
unixPathMax = #const sizeof(((struct sockaddr_un *)NULL)->sun_path)

-- We can't write an instance of 'Storable' for 'SockAddr' because
-- @sockaddr@ is a sum type of variable size but
-- 'Foreign.Storable.sizeOf' is required to be constant.

-- Note that on Darwin, the sockaddr structure must be zeroed before
-- use.

-- | Write the given 'SockAddr' to the given memory location.
pokeSockAddr :: Ptr a -> SockAddr -> IO ()
pokeSockAddr p sa@(SockAddrUnix path) = do
    let pathC = map castCharToCChar path
        len = length pathC
    when (len >= unixPathMax) $ error
      $ "pokeSockAddr: path is too long in SockAddrUnix " <> show path
      <> ", length " <> show len <> ", unixPathMax " <> show unixPathMax
    zeroMemory p $ fromIntegral $ sizeOfSockAddr sa
# if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
    (#poke struct sockaddr_un, sun_len) p ((#const sizeof(struct sockaddr_un)) :: Word8)
# endif
    (#poke struct sockaddr_un, sun_family) p ((#const AF_UNIX) :: CSaFamily)
    -- the buffer is already filled with nulls.
    pokeArray ((#ptr struct sockaddr_un, sun_path) p) pathC
pokeSockAddr p (SockAddrInet port addr) = do
    zeroMemory p (#const sizeof(struct sockaddr_in))
#if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
    (#poke struct sockaddr_in, sin_len) p ((#const sizeof(struct sockaddr_in)) :: Word8)
#endif
    (#poke struct sockaddr_in, sin_family) p ((#const AF_INET) :: CSaFamily)
    (#poke struct sockaddr_in, sin_port) p port
    (#poke struct sockaddr_in, sin_addr) p addr
pokeSockAddr p (SockAddrInet6 port flow addr scope) = do
    zeroMemory p (#const sizeof(struct sockaddr_in6))
# if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
    (#poke struct sockaddr_in6, sin6_len) p ((#const sizeof(struct sockaddr_in6)) :: Word8)
# endif
    (#poke struct sockaddr_in6, sin6_family) p ((#const AF_INET6) :: CSaFamily)
    (#poke struct sockaddr_in6, sin6_port) p port
    (#poke struct sockaddr_in6, sin6_flowinfo) p flow
    (#poke struct sockaddr_in6, sin6_addr) p (In6Addr addr)
    (#poke struct sockaddr_in6, sin6_scope_id) p scope

-- | Read a 'SockAddr' from the given memory location.
peekSockAddr :: Ptr SockAddr -> IO SockAddr
peekSockAddr p = do
  family <- (#peek struct sockaddr, sa_family) p
  case family :: CSaFamily of
    (#const AF_UNIX) -> do
        str <- peekCAString ((#ptr struct sockaddr_un, sun_path) p)
        return (SockAddrUnix str)
    (#const AF_INET) -> do
        addr <- (#peek struct sockaddr_in, sin_addr) p
        port <- (#peek struct sockaddr_in, sin_port) p
        return (SockAddrInet port addr)
    (#const AF_INET6) -> do
        port <- (#peek struct sockaddr_in6, sin6_port) p
        flow <- (#peek struct sockaddr_in6, sin6_flowinfo) p
        In6Addr addr <- (#peek struct sockaddr_in6, sin6_addr) p
        scope <- (#peek struct sockaddr_in6, sin6_scope_id) p
        return (SockAddrInet6 port flow addr scope)
    _ -> ioError $ userError $
      "Network.Socket.Types.peekSockAddr: address family '" ++
      show family ++ "' not supported."

------------------------------------------------------------------------

-- | The raw network byte order number is read using host byte order.
-- Therefore on little-endian architectures the byte order is swapped. For
-- example @127.0.0.1@ is represented as @0x0100007f@ on little-endian hosts
-- and as @0x7f000001@ on big-endian hosts.
--
-- For direct manipulation prefer 'hostAddressToTuple' and
-- 'tupleToHostAddress'.
type HostAddress = Word32

-- | Converts 'HostAddress' to representation-independent IPv4 quadruple.
-- For example for @127.0.0.1@ the function will return @(0x7f, 0, 0, 1)@
-- regardless of host endianness.
--
{- -- prop> tow == hostAddressToTuple (tupleToHostAddress tow) -}
hostAddressToTuple :: HostAddress -> (Word8, Word8, Word8, Word8)
hostAddressToTuple ha' =
    let ha = htonl ha'
        byte i = fromIntegral (ha `shiftR` i) :: Word8
    in (byte 24, byte 16, byte 8, byte 0)

hostAddressToTuple' :: HostAddress -> (Word8, Word8, Word8, Word8)
hostAddressToTuple' ha =
    let byte i = fromIntegral (ha `shiftR` i) :: Word8
    in (byte 24, byte 16, byte 8, byte 0)

-- | Converts IPv4 quadruple to 'HostAddress'.
tupleToHostAddress :: (Word8, Word8, Word8, Word8) -> HostAddress
tupleToHostAddress (b3, b2, b1, b0) =
    let x `sl` i = fromIntegral x `shiftL` i :: Word32
    in ntohl $ (b3 `sl` 24) .|. (b2 `sl` 16) .|. (b1 `sl` 8) .|. (b0 `sl` 0)

-- | Independent of endianness. For example @::1@ is stored as @(0, 0, 0, 1)@.
--
-- For direct manipulation prefer 'hostAddress6ToTuple' and
-- 'tupleToHostAddress6'.
type HostAddress6 = (Word32, Word32, Word32, Word32)

-- | Converts 'HostAddress6' to representation-independent IPv6 octuple.
--
{- -- prop> (w1,w2,w3,w4,w5,w6,w7,w8) == hostAddress6ToTuple (tupleToHostAddress6 (w1,w2,w3,w4,w5,w6,w7,w8)) -}
hostAddress6ToTuple :: HostAddress6 -> (Word16, Word16, Word16, Word16,
                                        Word16, Word16, Word16, Word16)
hostAddress6ToTuple (w3, w2, w1, w0) =
    let high, low :: Word32 -> Word16
        high w = fromIntegral (w `shiftR` 16)
        low w = fromIntegral w
    in (high w3, low w3, high w2, low w2, high w1, low w1, high w0, low w0)

-- | Converts IPv6 octuple to 'HostAddress6'.
tupleToHostAddress6 :: (Word16, Word16, Word16, Word16,
                        Word16, Word16, Word16, Word16) -> HostAddress6
tupleToHostAddress6 (w7, w6, w5, w4, w3, w2, w1, w0) =
    let add :: Word16 -> Word16 -> Word32
        high `add` low = (fromIntegral high `shiftL` 16) .|. (fromIntegral low)
    in (w7 `add` w6, w5 `add` w4, w3 `add` w2, w1 `add` w0)

-- The peek32 and poke32 functions work around the fact that the RFCs
-- don't require 32-bit-wide address fields to be present.  We can
-- only portably rely on an 8-bit field, s6_addr.

s6_addr_offset :: Int
s6_addr_offset = (#offset struct in6_addr, s6_addr)

peek32 :: Ptr a -> Int -> IO Word32
peek32 p i0 = do
    let i' = i0 * 4
        peekByte n = peekByteOff p (s6_addr_offset + i' + n) :: IO Word8
        a `sl` i = fromIntegral a `shiftL` i
    a0 <- peekByte 0
    a1 <- peekByte 1
    a2 <- peekByte 2
    a3 <- peekByte 3
    return ((a0 `sl` 24) .|. (a1 `sl` 16) .|. (a2 `sl` 8) .|. (a3 `sl` 0))

poke32 :: Ptr a -> Int -> Word32 -> IO ()
poke32 p i0 a = do
    let i' = i0 * 4
        pokeByte n = pokeByteOff p (s6_addr_offset + i' + n)
        x `sr` i = fromIntegral (x `shiftR` i) :: Word8
    pokeByte 0 (a `sr` 24)
    pokeByte 1 (a `sr` 16)
    pokeByte 2 (a `sr`  8)
    pokeByte 3 (a `sr`  0)

-- | Private newtype proxy for the Storable instance. To avoid orphan instances.
newtype In6Addr = In6Addr HostAddress6

#if __GLASGOW_HASKELL__ < 800
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
#endif

instance Storable In6Addr where
    sizeOf    ~_ = #const sizeof(struct in6_addr)
    alignment ~_ = #alignment struct in6_addr

    peek p = do
        a <- peek32 p 0
        b <- peek32 p 1
        c <- peek32 p 2
        d <- peek32 p 3
        return $ In6Addr (a, b, c, d)

    poke p (In6Addr (a, b, c, d)) = do
        poke32 p 0 a
        poke32 p 1 b
        poke32 p 2 c
        poke32 p 3 d

------------------------------------------------------------------------
-- Read and Show instance for pattern-based integral newtypes

socktypeBijection :: Bijection SocketType String
socktypeBijection =
    [ (UnsupportedSocketType, "UnsupportedSocketType")
    , (Stream, "Stream")
    , (Datagram, "Datagram")
    , (Raw, "Raw")
    , (RDM, "RDM")
    , (SeqPacket, "SeqPacket")
    , (NoSocketType, "NoSocketType")
    ]

instance Show SocketType where
    showsPrec = bijectiveShow socktypeBijection def
      where
        gst = "GeneralSocketType"
        def = defShow gst packSocketType _showInt

instance Read SocketType where
    readPrec = bijectiveRead socktypeBijection def
      where
        gst = "GeneralSocketType"
        def = defRead gst unpackSocketType _readInt

familyBijection :: Bijection Family String
familyBijection =
    [ (UnsupportedFamily, "UnsupportedFamily")
    , (AF_UNSPEC, "AF_UNSPEC")
    , (AF_UNIX, "AF_UNIX")
    , (AF_INET, "AF_INET")
    , (AF_INET6, "AF_INET6")
    , (AF_IMPLINK, "AF_IMPLINK")
    , (AF_PUP, "AF_PUP")
    , (AF_CHAOS, "AF_CHAOS")
    , (AF_NS, "AF_NS")
    , (AF_NBS, "AF_NBS")
    , (AF_ECMA, "AF_ECMA")
    , (AF_DATAKIT, "AF_DATAKIT")
    , (AF_CCITT, "AF_CCITT")
    , (AF_SNA, "AF_SNA")
    , (AF_DECnet, "AF_DECnet")
    , (AF_DLI, "AF_DLI")
    , (AF_LAT, "AF_LAT")
    , (AF_HYLINK, "AF_HYLINK")
    , (AF_APPLETALK, "AF_APPLETALK")
    , (AF_ROUTE, "AF_ROUTE")
    , (AF_NETBIOS, "AF_NETBIOS")
    , (AF_NIT, "AF_NIT")
    , (AF_802, "AF_802")
    , (AF_ISO, "AF_ISO")
    , (AF_OSI, "AF_OSI")
    , (AF_NETMAN, "AF_NETMAN")
    , (AF_X25, "AF_X25")
    , (AF_AX25, "AF_AX25")
    , (AF_OSINET, "AF_OSINET")
    , (AF_GOSSIP, "AF_GOSSIP")
    , (AF_IPX, "AF_IPX")
    , (Pseudo_AF_XTP, "Pseudo_AF_XTP")
    , (AF_CTF, "AF_CTF")
    , (AF_WAN, "AF_WAN")
    , (AF_SDL, "AF_SDL")
    , (AF_NETWARE, "AF_NETWARE")
    , (AF_NDD, "AF_NDD")
    , (AF_INTF, "AF_INTF")
    , (AF_COIP, "AF_COIP")
    , (AF_CNT, "AF_CNT")
    , (Pseudo_AF_RTIP, "Pseudo_AF_RTIP")
    , (Pseudo_AF_PIP, "Pseudo_AF_PIP")
    , (AF_SIP, "AF_SIP")
    , (AF_ISDN, "AF_ISDN")
    , (Pseudo_AF_KEY, "Pseudo_AF_KEY")
    , (AF_NATM, "AF_NATM")
    , (AF_ARP, "AF_ARP")
    , (Pseudo_AF_HDRCMPLT, "Pseudo_AF_HDRCMPLT")
    , (AF_ENCAP, "AF_ENCAP")
    , (AF_LINK, "AF_LINK")
    , (AF_RAW, "AF_RAW")
    , (AF_RIF, "AF_RIF")
    , (AF_NETROM, "AF_NETROM")
    , (AF_BRIDGE, "AF_BRIDGE")
    , (AF_ATMPVC, "AF_ATMPVC")
    , (AF_ROSE, "AF_ROSE")
    , (AF_NETBEUI, "AF_NETBEUI")
    , (AF_SECURITY, "AF_SECURITY")
    , (AF_PACKET, "AF_PACKET")
    , (AF_ASH, "AF_ASH")
    , (AF_ECONET, "AF_ECONET")
    , (AF_ATMSVC, "AF_ATMSVC")
    , (AF_IRDA, "AF_IRDA")
    , (AF_PPPOX, "AF_PPPOX")
    , (AF_WANPIPE, "AF_WANPIPE")
    , (AF_BLUETOOTH, "AF_BLUETOOTH")
    , (AF_CAN, "AF_CAN")
    ]

instance Show Family where
    showsPrec = bijectiveShow familyBijection def
      where
        gf = "GeneralFamily"
        def = defShow gf packFamily _showInt

instance Read Family where
    readPrec = bijectiveRead familyBijection def
      where
        gf = "GeneralFamily"
        def = defRead gf unpackFamily _readInt

-- Print "n" instead of "PortNum n".
instance Show PortNumber where
  showsPrec p (PortNum pn) = showsPrec p pn

-- Read "n" instead of "PortNum n".
instance Read PortNumber where
  readPrec = safeInt

------------------------------------------------------------------------
-- Helper functions

foreign import ccall unsafe "string.h" memset :: Ptr a -> CInt -> CSize -> IO ()

-- | Zero a structure.
zeroMemory :: Ptr a -> CSize -> IO ()
zeroMemory dest nbytes = memset dest 0 (fromIntegral nbytes)