Skip to content

Commit 569d5d1

Browse files
committed
Socket type and family as CInt patterns
The current sum-type model for Socket types and families is not extensible, and makes it needlessly difficult to perform generic operations on sockets, see e.g. #427 This commit, simplifies the model by replacing the sum-types in question with newtypes around CInt + patterns for the known constant values. It also adds the SO_DOMAIN and SO_PROTOCOL options (when available on the target system). The "Read" instance for "Family" is for simplicify limited to just the address families actually supported by the library (unspec, inet, inet6 and unix). The rest could be added if deemed worth the trouble.
1 parent ef42779 commit 569d5d1

File tree

6 files changed

+698
-459
lines changed

6 files changed

+698
-459
lines changed

Network/Socket.hs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ module Network.Socket
134134

135135
-- * Socket options
136136
, SocketOption(SockOpt
137-
,Debug,ReuseAddr,Type,SoError,DontRoute,Broadcast
138-
,SendBuffer,RecvBuffer,KeepAlive,OOBInline,TimeToLive
139-
,MaxSegment,NoDelay,Cork,Linger,ReusePort
137+
,Debug,ReuseAddr,SoDomain,Type,SoProtocol,SoError,DontRoute
138+
,Broadcast,SendBuffer,RecvBuffer,KeepAlive,OOBInline
139+
,TimeToLive,MaxSegment,NoDelay,Cork,Linger,ReusePort
140140
,RecvLowWater,SendLowWater,RecvTimeOut,SendTimeOut
141141
,UseLoopBack,UserTimeout,IPv6Only
142142
,RecvIPv4TTL,RecvIPv4TOS,RecvIPv4PktInfo
@@ -160,11 +160,22 @@ module Network.Socket
160160
, mkSocket
161161
, socketToHandle
162162
-- ** Types of Socket
163-
, SocketType(..)
163+
, SocketType(GeneralSocketType, UnsupportedSocketType, NoSocketType
164+
, Stream, Datagram, Raw, RDM, SeqPacket)
164165
, isSupportedSocketType
165166
, getSocketType
166167
-- ** Family
167-
, Family(..)
168+
, Family(GeneralFamily, UnsupportedFamily
169+
,AF_UNSPEC,AF_UNIX,AF_INET,AF_INET6,AF_IMPLINK,AF_PUP,AF_CHAOS
170+
,AF_NS,AF_NBS,AF_ECMA,AF_DATAKIT,AF_CCITT,AF_SNA,AF_DECnet
171+
,AF_DLI,AF_LAT,AF_HYLINK,AF_APPLETALK,AF_ROUTE,AF_NETBIOS
172+
,AF_NIT,AF_802,AF_ISO,AF_OSI,AF_NETMAN,AF_X25,AF_AX25,AF_OSINET
173+
,AF_GOSSIP,AF_IPX,Pseudo_AF_XTP,AF_CTF,AF_WAN,AF_SDL,AF_NETWARE
174+
,AF_NDD,AF_INTF,AF_COIP,AF_CNT,Pseudo_AF_RTIP,Pseudo_AF_PIP
175+
,AF_SIP,AF_ISDN,Pseudo_AF_KEY,AF_NATM,AF_ARP,Pseudo_AF_HDRCMPLT
176+
,AF_ENCAP,AF_LINK,AF_RAW,AF_RIF,AF_NETROM,AF_BRIDGE,AF_ATMPVC
177+
,AF_ROSE,AF_NETBEUI,AF_SECURITY,AF_PACKET,AF_ASH,AF_ECONET
178+
,AF_ATMSVC,AF_IRDA,AF_PPPOX,AF_WANPIPE,AF_BLUETOOTH,AF_CAN)
168179
, isSupportedFamily
169180
, packFamily
170181
, unpackFamily

Network/Socket/Info.hsc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,17 @@ instance Storable AddrInfo where
124124
then return Nothing
125125
else Just <$> peekCString ai_canonname_ptr
126126

127-
socktype <- unpackSocketType' "AddrInfo.peek" ai_socktype
128127
return $ AddrInfo {
129128
addrFlags = unpackBits aiFlagMapping ai_flags
130129
, addrFamily = unpackFamily ai_family
131-
, addrSocketType = socktype
130+
, addrSocketType = unpackSocketType ai_socktype
132131
, addrProtocol = ai_protocol
133132
, addrAddress = ai_addr
134133
, addrCanonName = ai_canonname
135134
}
136135

137136
poke p (AddrInfo flags family sockType protocol _ _) = do
138-
c_stype <- packSocketTypeOrThrow "AddrInfo.poke" sockType
137+
let c_stype = packSocketType sockType
139138

140139
(#poke struct addrinfo, ai_flags) p (packBits aiFlagMapping flags)
141140
(#poke struct addrinfo, ai_family) p (packFamily family)

Network/Socket/Options.hsc

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
module Network.Socket.Options (
1111
SocketOption(SockOpt
12-
,Debug,ReuseAddr,Type,SoError,DontRoute,Broadcast
13-
,SendBuffer,RecvBuffer,KeepAlive,OOBInline,TimeToLive
12+
,Debug,ReuseAddr,SoDomain,Type,SoProtocol,SoError,DontRoute
13+
,Broadcast,SendBuffer,RecvBuffer,KeepAlive,OOBInline,TimeToLive
1414
,MaxSegment,NoDelay,Cork,Linger,ReusePort
1515
,RecvLowWater,SendLowWater,RecvTimeOut,SendTimeOut
1616
,UseLoopBack,UserTimeout,IPv6Only
@@ -53,8 +53,7 @@ isSupportedSocketOption opt = opt /= SockOpt (-1) (-1)
5353
--
5454
-- Since: 3.0.1.0
5555
getSocketType :: Socket -> IO SocketType
56-
getSocketType s = (fromMaybe NoSocketType . unpackSocketType . fromIntegral)
57-
<$> getSocketOption s Type
56+
getSocketType s = unpackSocketType <$> getSockOpt s Type
5857

5958
#ifdef SOL_SOCKET
6059
-- | SO_DEBUG
@@ -71,13 +70,31 @@ pattern ReuseAddr = SockOpt (#const SOL_SOCKET) (#const SO_REUSEADDR)
7170
#else
7271
pattern ReuseAddr = SockOpt (-1) (-1)
7372
#endif
74-
-- | SO_TYPE
73+
74+
-- | SO_DOMAIN, read-only
75+
pattern SoDomain :: SocketOption
76+
#ifdef SO_DOMAIN
77+
pattern SoDomain = SockOpt (#const SOL_SOCKET) (#const SO_DOMAIN)
78+
#else
79+
pattern SoDomain = SockOpt (-1) (-1)
80+
#endif
81+
82+
-- | SO_TYPE, read-only
7583
pattern Type :: SocketOption
7684
#ifdef SO_TYPE
7785
pattern Type = SockOpt (#const SOL_SOCKET) (#const SO_TYPE)
7886
#else
7987
pattern Type = SockOpt (-1) (-1)
8088
#endif
89+
90+
-- | SO_PROTOCOL, read-only
91+
pattern SoProtocol :: SocketOption
92+
#ifdef SO_PROTOCOL
93+
pattern SoProtocol = SockOpt (#const SOL_SOCKET) (#const SO_PROTOCOL)
94+
#else
95+
pattern SoProtocol = SockOpt (-1) (-1)
96+
#endif
97+
8198
-- | SO_ERROR
8299
pattern SoError :: SocketOption
83100
#ifdef SO_ERROR

Network/Socket/Syscall.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ socket family stype protocol = E.bracketOnError create c_close $ \fd -> do
8484
return s
8585
where
8686
create = do
87-
c_stype <- modifyFlag <$> packSocketTypeOrThrow "socket" stype
87+
let c_stype = modifyFlag $ packSocketType stype
8888
throwSocketErrorIfMinus1Retry "Network.Socket.socket" $
8989
c_socket (packFamily family) c_stype protocol
9090

0 commit comments

Comments
 (0)