1
1
{-# LANGUAGE CPP #-}
2
2
{-# LANGUAGE PatternSynonyms #-}
3
3
{-# LANGUAGE ScopedTypeVariables #-}
4
+ {-# LANGUAGE RecordWildCards #-}
4
5
{-# LANGUAGE ViewPatterns #-}
5
6
6
7
#include "HsNet.h"
@@ -25,12 +26,15 @@ module Network.Socket.Options (
25
26
, setSockOpt
26
27
) where
27
28
29
+ import qualified Text.Read as P
30
+
28
31
import Foreign.Marshal.Alloc (alloca )
29
32
import Foreign.Marshal.Utils (with )
30
33
31
34
import Network.Socket.Imports
32
35
import Network.Socket.Internal
33
36
import Network.Socket.Types
37
+ import Network.Socket.ReadShow
34
38
35
39
-----------------------------------------------------------------------------
36
40
-- Socket Properties
@@ -39,10 +43,10 @@ import Network.Socket.Types
39
43
--
40
44
-- The existence of a constructor does not imply that the relevant option
41
45
-- is supported on your system: see 'isSupportedSocketOption'
42
- data SocketOption = SockOpt {
43
- sockOptLevel :: ! CInt
44
- , sockOptName :: ! CInt
45
- } deriving (Eq , Show )
46
+ data SocketOption = SockOpt
47
+ ! CInt -- ^ Option Level
48
+ ! CInt -- ^ Option Name
49
+ deriving (Eq )
46
50
47
51
-- | Does the 'SocketOption' exist on this system?
48
52
isSupportedSocketOption :: SocketOption -> Bool
@@ -141,7 +145,7 @@ pattern OOBInline :: SocketOption
141
145
#ifdef SO_OOBINLINE
142
146
pattern OOBInline = SockOpt (# const SOL_SOCKET ) (# const SO_OOBINLINE )
143
147
#else
144
- pattern OOBINLINE = SockOpt (- 1 ) (- 1 )
148
+ pattern OOBInline = SockOpt (- 1 ) (- 1 )
145
149
#endif
146
150
-- | SO_LINGER: timeout in seconds, 0 means disabling/disabled.
147
151
pattern Linger :: SocketOption
@@ -376,6 +380,63 @@ getSockOpt s (SockOpt level opt) = do
376
380
c_getsockopt fd level opt ptr ptr_sz
377
381
peek ptr
378
382
383
+
384
+ socketOptionPairs :: [Pair SocketOption String ]
385
+ socketOptionPairs =
386
+ [ (Debug , " Debug" )
387
+ , (ReuseAddr , " ReuseAddr" )
388
+ , (SoDomain , " SoDomain" )
389
+ , (Type , " Type" )
390
+ , (SoProtocol , " SoProtocol" )
391
+ , (SoError , " SoError" )
392
+ , (DontRoute , " DontRoute" )
393
+ , (Broadcast , " Broadcast" )
394
+ , (SendBuffer , " SendBuffer" )
395
+ , (RecvBuffer , " RecvBuffer" )
396
+ , (KeepAlive , " KeepAlive" )
397
+ , (OOBInline , " OOBInline" )
398
+ , (Linger , " Linger" )
399
+ , (ReusePort , " ReusePort" )
400
+ , (RecvLowWater , " RecvLowWater" )
401
+ , (SendLowWater , " SendLowWater" )
402
+ , (RecvTimeOut , " RecvTimeOut" )
403
+ , (SendTimeOut , " SendTimeOut" )
404
+ , (UseLoopBack , " UseLoopBack" )
405
+ , (MaxSegment , " MaxSegment" )
406
+ , (NoDelay , " NoDelay" )
407
+ , (UserTimeout , " UserTimeout" )
408
+ , (Cork , " Cork" )
409
+ , (TimeToLive , " TimeToLive" )
410
+ , (RecvIPv4TTL , " RecvIPv4TTL" )
411
+ , (RecvIPv4TOS , " RecvIPv4TOS" )
412
+ , (RecvIPv4PktInfo , " RecvIPv4PktInfo" )
413
+ , (IPv6Only , " IPv6Only" )
414
+ , (RecvIPv6HopLimit , " RecvIPv6HopLimit" )
415
+ , (RecvIPv6TClass , " RecvIPv6TClass" )
416
+ , (RecvIPv6PktInfo , " RecvIPv6PktInfo" )
417
+ ]
418
+
419
+ socketOptionBijection :: Bijection SocketOption String
420
+ socketOptionBijection = Bijection {.. }
421
+ where
422
+ cso = " CustomSockOpt"
423
+ _parse :: String -> (CInt , CInt )
424
+ _parse xy =
425
+ let (xs, (' _' : ys)) = break (== ' _' ) xy
426
+ in (read xs, read ys)
427
+ defFwd = \ (CustomSockOpt (n,m)) -> cso++ show n++ " _" ++ show m
428
+ defBwd s = case splitAt (length cso) s of
429
+ (" CustomSockOpt" , nm) -> CustomSockOpt $ _parse nm
430
+ _ -> error " socketOptionBijection: exception in WIP ReadShow code"
431
+ pairs = socketOptionPairs
432
+
433
+ instance Show SocketOption where
434
+ show = forward socketOptionBijection
435
+
436
+ instance Read SocketOption where
437
+ readPrec = P. lexP >>= \ (P. Ident x) -> return $ backward socketOptionBijection x
438
+
439
+
379
440
foreign import CALLCONV unsafe " getsockopt"
380
441
c_getsockopt :: CInt -> CInt -> CInt -> Ptr a -> Ptr CInt -> IO CInt
381
442
foreign import CALLCONV unsafe " setsockopt"
0 commit comments