network 2.6.3.6 → 2.7.0.0
raw patch · 11 files changed
+432/−201 lines, 11 filesdep +directory
Dependencies added: directory
Files
- CHANGELOG.md +17/−3
- Network.hs +2/−1
- Network/BSD.hsc +4/−20
- Network/Socket.hsc +292/−159
- Network/Socket/ByteString.hsc +2/−1
- Network/Socket/ByteString/Lazy/Posix.hs +1/−0
- Network/Socket/Types.hsc +13/−14
- configure.ac +2/−2
- examples/EchoServer.hs +4/−0
- network.cabal +2/−1
- tests/SimpleSpec.hs +93/−0
CHANGELOG.md view
@@ -1,6 +1,20 @@-## Version 2.6.3.6- * Removed unnecessary withMVar, which caused locking on close.- [#330](https://github.com/haskell/network/pull/330)+## Version 2.7.0.0+ * Obsoleting the Network module.+ * Obsoleting the Network.BSD module.+ * Obsoleting APIs: MkSocket, htonl, ntohl,+ getPeerCred, getPeerEid,+ send, sendTo, recv, recvFrom, recvLen,+ inet_addr, inet_ntoa,+ isConnected, isBound, isListening, isReadable, isWritable,+ aNY_PORT, iNADDR_ANY, iN6ADDR_ANY, sOMAXCONN,+ sOL_SOCKET, sCM_RIGHTS,+ packFamily, unpackFamily, packSocketType+ * Do not closeFd within sendFd+ [#271](https://github.com/haskell/network/pull/271)+ * Exporting ifNameToIndex and ifIndexToName from Network.Socket.+ * New APIs: setCloseOnExecIfNeeded, getCloseOnExec and getNonBlock+ * New APIs: isUnixDomainSocketAvailable and getPeerCredential+ * socketPair, sendFd and recvFd are exported even on Windows. ## Version 2.6.3.5 * Reverting "Do not closeFd within sendFd"
Network.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}+{-# OPTIONS_HADDOCK hide #-} ----------------------------------------------------------------------------- -- | -- Module : Network@@ -25,7 +26,7 @@ #define IPV6_SOCKET_SUPPORT 1 #endif -module Network+module Network {-# DEPRECATED "The high level Network interface is no longer supported. Please use Network.Socket." #-} ( -- * Basic data types Socket
Network/BSD.hsc view
@@ -1,4 +1,6 @@ {-# LANGUAGE CPP, ForeignFunctionInterface #-}+{-# OPTIONS_HADDOCK hide #-}+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} ----------------------------------------------------------------------------- -- | -- Module : Network.BSD@@ -16,7 +18,7 @@ #include "HsNet.h" -module Network.BSD+module Network.BSD {-# DEPRECATED "This platform dependent module is no longer supported." #-} ( -- * Host names HostName@@ -102,7 +104,7 @@ #if defined(HAVE_WINSOCK2_H) import Foreign.C.Types ( CShort ) #endif-import Foreign.C.Types ( CInt(..), CUInt(..), CULong(..), CSize(..) )+import Foreign.C.Types ( CInt(..), CULong(..), CSize(..) ) import Foreign.Ptr (Ptr, nullPtr) import Foreign.Storable (Storable(..)) import Foreign.Marshal.Array (allocaArray0, peekArray0)@@ -512,24 +514,6 @@ setNetworkEntry stayOpen getEntries (getNetworkEntry) (endNetworkEntry) #endif---- ------------------------------------------------------------------------------ Interface names--#if defined(HAVE_IF_NAMETOINDEX)---- returns the index of the network interface corresponding to the name ifname.-ifNameToIndex :: String -> IO (Maybe Int)-ifNameToIndex ifname = do- index <- withCString ifname c_if_nametoindex- -- On failure zero is returned. We'll return Nothing.- return $ if index == 0 then Nothing else Just $ fromIntegral index--foreign import CALLCONV safe "if_nametoindex"- c_if_nametoindex :: CString -> IO CUInt--#endif- -- Mutex for name service lockdown
Network/Socket.hsc view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP, ScopedTypeVariables, RecordWildCards #-} {-# OPTIONS_GHC -fno-warn-orphans #-}+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} ----------------------------------------------------------------------------- -- | -- Module : Network.Socket@@ -10,13 +11,9 @@ -- Stability : provisional -- Portability : portable ----- The "Network.Socket" module is for when you want full control over--- sockets. Essentially the entire C socket API is exposed through--- this module; in general the operations follow the behaviour of the C--- functions of the same name (consult your favourite Unix networking book).------ A higher level interface to networking operations is provided--- through the module "Network".+-- This is the main module of the network package supposed to be+-- used with either "Network.Socket.ByteString" or+-- "Network.Socket.ByteString.Lazy" for sending/receiving. -- -- Here are two minimal example programs using the TCP/IP protocol: a -- server that echoes all data that it receives back (servicing only@@ -48,6 +45,10 @@ -- > sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) -- > setSocketOption sock ReuseAddr 1 -- > bind sock (addrAddress addr)+-- > -- If the prefork technique is not used,+-- > -- set CloseOnExec for the security reasons.+-- > let fd = fdSocket sock+-- > setCloseOnExecIfNeeded fd -- > listen sock 10 -- > return sock -- > loop sock = forever $ do@@ -95,121 +96,125 @@ module Network.Socket (- -- * Types- Socket(..)- , Family(..)- , isSupportedFamily+ -- * Initialisation+ withSocketsDo+ -- * Address information+ , getAddrInfo+ -- ** Types+ , HostName+ , ServiceName+ , AddrInfo(..)+ , defaultHints+ -- ** Flags+ , AddrInfoFlag(..)+ , addrInfoFlagImplemented+ -- * Socket operations+ , connect+ , bind+ , listen+ , accept+ -- ** Closing+ , close+ , shutdown+ , ShutdownCmd(..)+ -- * Socket options+ , SocketOption(..)+ , isSupportedSocketOption+ , getSocketOption+ , setSocketOption+ -- * Socket+ , Socket(..)+ , socket+ , fdSocket+ , mkSocket+ , socketToHandle+ -- ** Types of Socket , SocketType(..) , isSupportedSocketType+ -- ** Family+ , Family(..)+ , isSupportedFamily+ -- ** Protocol number+ , ProtocolNumber+ , defaultProtocol+ -- * Socket address , SockAddr(..) , isSupportedSockAddr- , SocketStatus(..)+ , getPeerName+ , getSocketName+ -- ** Host address , HostAddress , hostAddressToTuple , tupleToHostAddress #if defined(IPV6_SOCKET_SUPPORT)+ -- ** Host address6 , HostAddress6 , hostAddress6ToTuple , tupleToHostAddress6+ -- ** Flow Info , FlowInfo+ -- ** Scope ID , ScopeID+# if defined(HAVE_IF_NAMETOINDEX)+ , ifNameToIndex+ , ifIndexToName+# endif #endif- , htonl- , ntohl- , ShutdownCmd(..)- , ProtocolNumber- , defaultProtocol+ -- ** Port number , PortNumber(..)- -- PortNumber is used non-abstractly in Network.BSD. ToDo: remove- -- this use and make the type abstract.-- -- * Address operations-- , HostName- , ServiceName-+ , defaultPort+ , socketPort+ -- * UNIX-domain socket+ , isUnixDomainSocketAvailable+ , socketPair+ , sendFd+ , recvFd+ , getPeerCredential #if defined(IPV6_SOCKET_SUPPORT)- , AddrInfo(..)-- , AddrInfoFlag(..)- , addrInfoFlagImplemented-- , defaultHints-- , getAddrInfo-+ -- * Name information , NameInfoFlag(..)- , getNameInfo #endif-- -- * Socket operations- , socket-#if defined(DOMAIN_SOCKET_SUPPORT)- , socketPair-#endif- , connect- , bind- , listen- , accept- , getPeerName- , getSocketName--#if defined(HAVE_STRUCT_UCRED) || defined(HAVE_GETPEEREID)- -- get the credentials of our domain socket peer.- , getPeerCred-#if defined(HAVE_GETPEEREID)- , getPeerEid-#endif-#endif-- , socketPort-- , socketToHandle-- -- ** Sending and receiving data- -- *** Sending and receiving with String- -- $sendrecv+ -- * Low level operations+ , setCloseOnExecIfNeeded+ , getCloseOnExec+ , setNonBlockIfNeeded+ , getNonBlock+ -- * Sending and receiving data+ , sendBuf+ , recvBuf+ , sendBufTo+ , recvBufFrom+ -- * Special constants+ , maxListenQueue+ -- * Deprecated+ -- ** Deprecated sending and receiving , send , sendTo , recv , recvFrom , recvLen-- -- *** Sending and receiving with a buffer- , sendBuf- , recvBuf- , sendBufTo- , recvBufFrom-- -- ** Misc+ -- ** Deprecated address functions+ , htonl+ , ntohl , inet_addr , inet_ntoa-- , shutdown- , close-- -- ** Predicates on sockets+ -- ** Deprecated socket operations+ , bindSocket+ , sClose+ -- ** Deprecated socket status+ , SocketStatus(..) -- fixme , isConnected , isBound , isListening , isReadable , isWritable-- -- * Socket options- , SocketOption(..)- , isSupportedSocketOption- , getSocketOption- , setSocketOption-- -- * File descriptor transmission-#ifdef DOMAIN_SOCKET_SUPPORT- , sendFd- , recvFd--#endif-- -- * Special constants+ , sIsConnected+ , sIsBound+ , sIsListening+ , sIsReadable+ , sIsWritable+ -- ** Deprecated special constants , aNY_PORT , iNADDR_ANY #if defined(IPV6_SOCKET_SUPPORT)@@ -220,35 +225,18 @@ #ifdef SCM_RIGHTS , sCM_RIGHTS #endif- , maxListenQueue-- -- * Initialisation- , withSocketsDo-- -- * Very low level operations- -- in case you ever want to get at the underlying file descriptor..- , fdSocket- , mkSocket- , setNonBlockIfNeeded-- -- * Deprecated aliases- -- $deprecated-aliases- , bindSocket- , sClose- , sIsConnected- , sIsBound- , sIsListening- , sIsReadable- , sIsWritable-- -- * Internal-- -- | The following are exported ONLY for use in the BSD module and- -- should not be used anywhere else.-+ -- ** Decrecated internal functions , packFamily , unpackFamily , packSocketType+ -- ** Decrecated UNIX-domain functions+#if defined(HAVE_STRUCT_UCRED) || defined(HAVE_GETPEEREID)+ -- get the credentials of our domain socket peer.+ , getPeerCred+#if defined(HAVE_GETPEEREID)+ , getPeerEid+#endif+#endif ) where import Data.Bits@@ -260,7 +248,7 @@ import Foreign.Storable (Storable(..)) import Foreign.C.Error import Foreign.C.String (CString, withCString, withCStringLen, peekCString, peekCStringLen)-import Foreign.C.Types (CUInt, CChar)+import Foreign.C.Types (CUInt(..), CChar) import Foreign.C.Types (CInt(..), CSize(..)) import Foreign.Marshal.Alloc ( alloca, allocaBytes ) import Foreign.Marshal.Array ( peekArray )@@ -269,6 +257,7 @@ import System.IO import Control.Monad (liftM, when) +import qualified Control.Exception as E import Control.Concurrent.MVar import Data.Typeable import System.IO.Error@@ -281,7 +270,6 @@ import GHC.Conc (closeFdWith) ##endif # if defined(mingw32_HOST_OS)-import qualified Control.Exception as E import GHC.Conc (asyncDoProc) import GHC.IO.FD (FD(..), readRawBufferPtr, writeRawBufferPtr) import Foreign (FunPtr)@@ -350,6 +338,7 @@ withSocketsDo $ return () return $ MkSocket fd fam sType pNum mStat +-- | Obtaining the file descriptor from a socket. fdSocket :: Socket -> CInt fdSocket (MkSocket fd _ _ _ _) = fd @@ -405,11 +394,7 @@ -- -- >>> let hints = defaultHints { addrFlags = [AI_NUMERICHOST, AI_NUMERICSERV], addrSocketType = Stream } -- >>> addr:_ <- getAddrInfo (Just hints) (Just "127.0.0.1") (Just "5000")--- >>> sock@(MkSocket _ fam stype _ _) <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)--- >>> fam--- AF_INET--- >>> stype--- Stream+-- >>> sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) -- >>> bind sock (addrAddress addr) -- >>> getSocketName sock -- 127.0.0.1:5000@@ -442,11 +427,11 @@ -- family, socket type, and protocol number. Address family, socket -- type, and protocol number are as for the 'socket' function above. -- Availability: Unix.-#if defined(DOMAIN_SOCKET_SUPPORT) socketPair :: Family -- Family Name (usually AF_INET or AF_INET6) -> SocketType -- Socket Type (usually Stream) -> ProtocolNumber -- Protocol Number -> IO (Socket, Socket) -- unnamed and connected.+#if defined(DOMAIN_SOCKET_SUPPORT) socketPair family stype protocol = do allocaBytes (2 * sizeOf (1 :: CInt)) $ \ fdArr -> do c_stype <- packSocketTypeOrThrow "socketPair" stype@@ -463,23 +448,87 @@ foreign import ccall unsafe "socketpair" c_socketpair :: CInt -> CInt -> CInt -> Ptr CInt -> IO CInt+#else+socketPair _ _ _ = error "Network.Socket.socketPair" #endif --- | Set the socket to nonblocking, if applicable to this platform.------ Depending on the platform this is required when using sockets from file--- descriptors that are passed in through 'recvFd' or other means.+-----------------------------------------------------------------------------++#if defined(mingw32_HOST_OS)+#else+fGetFd :: CInt+fGetFd = #const F_GETFD+fGetFl :: CInt+fGetFl = #const F_GETFL+fdCloexec :: CInt+fdCloexec = #const FD_CLOEXEC+oNonBlock :: CInt+oNonBlock = #const O_NONBLOCK+# if defined(HAVE_ACCEPT4)+sockNonBlock :: CInt+sockNonBlock = #const SOCK_NONBLOCK+sockCloexec :: CInt+sockCloexec = #const SOCK_CLOEXEC+# endif+#endif++-- | Set the nonblocking flag on Unix.+-- On Windows, nothing is done. setNonBlockIfNeeded :: CInt -> IO () setNonBlockIfNeeded fd = System.Posix.Internals.setNonBlockingFD fd True +-- | Set the close_on_exec flag on Unix.+-- On Windows, nothing is done.+--+-- Since 2.7.0.0.+setCloseOnExecIfNeeded :: CInt -> IO ()+#if defined(mingw32_HOST_OS)+setCloseOnExecIfNeeded _ = return ()+#else+setCloseOnExecIfNeeded fd = System.Posix.Internals.setCloseOnExec fd+#endif++#if !defined(mingw32_HOST_OS)+foreign import ccall unsafe "fcntl"+ c_fcntl_read :: CInt -> CInt -> CInt -> IO CInt+#endif++-- | Get the nonblocking flag.+-- On Windows, this function always returns 'False'.+--+-- Since 2.7.0.0.+getCloseOnExec :: CInt -> IO Bool+#if defined(mingw32_HOST_OS)+getCloseOnExec _ = return False+#else+getCloseOnExec fd = do+ flags <- c_fcntl_read fd fGetFd 0+ let ret = flags .&. fdCloexec+ return (ret /= 0)+#endif++-- | Get the close_on_exec flag.+-- On Windows, this function always returns 'False'.+--+-- Since 2.7.0.0.+getNonBlock :: CInt -> IO Bool+#if defined(mingw32_HOST_OS)+getNonBlock _ = return False+#else+getNonBlock fd = do+ flags <- c_fcntl_read fd fGetFl 0+ let ret = flags .&. oNonBlock+ return (ret /= 0)+#endif+ ----------------------------------------------------------------------------- -- Binding a socket -- | Bind the socket to an address. The socket must not already be -- bound. The 'Family' passed to @bind@ must be the -- same as that passed to 'socket'. If the special port number--- 'aNY_PORT' is passed then the system assigns the next available+-- 'defaultPort' is passed then the system assigns the next available -- use port. bind :: Socket -- Unconnected Socket -> SockAddr -- Address to Bind to@@ -578,8 +627,7 @@ -> IO (Socket, -- Readable Socket SockAddr) -- Peer details -accept sock@(MkSocket s family stype protocol status) = do- currentStatus <- readMVar status+accept sock@(MkSocket s family stype protocol status) = withMVar status $ \currentStatus -> do if not $ isAcceptable family stype currentStatus then ioError $ userError $@@ -608,11 +656,12 @@ # ifdef HAVE_ACCEPT4 new_sock <- throwSocketErrorIfMinus1RetryMayBlock "Network.Socket.accept" (threadWaitRead (fromIntegral s))- (c_accept4 s sockaddr ptr_len (#const SOCK_NONBLOCK))+ (c_accept4 s sockaddr ptr_len (sockNonBlock .|. sockCloexec)) # else new_sock <- throwSocketErrorWaitRead sock "Network.Socket.accept" (c_accept s sockaddr ptr_len) setNonBlockIfNeeded new_sock+ setCloseOnExecIfNeeded new_sock # endif /* HAVE_ACCEPT4 */ #endif addr <- peekSockAddr sockaddr@@ -651,7 +700,7 @@ -- -- NOTE: blocking on Windows unless you compile with -threaded (see -- GHC ticket #1129)-{-# WARNING sendTo "Use sendTo defined in \"Network.Socket.ByteString\"" #-}+{-# DEPRECATED sendTo "Use sendTo defined in \"Network.Socket.ByteString\"" #-} sendTo :: Socket -- (possibly) bound/connected Socket -> String -- Data to send -> SockAddr@@ -683,7 +732,7 @@ -- -- NOTE: blocking on Windows unless you compile with -threaded (see -- GHC ticket #1129)-{-# WARNING recvFrom "Use recvFrom defined in \"Network.Socket.ByteString\"" #-}+{-# DEPRECATED recvFrom "Use recvFrom defined in \"Network.Socket.ByteString\"" #-} recvFrom :: Socket -> Int -> IO (String, Int, SockAddr) recvFrom sock nbytes = allocaBytes nbytes $ \ptr -> do@@ -732,7 +781,7 @@ -- responsible for ensuring that all data has been sent. -- -- Sending data to closed socket may lead to undefined behaviour.-{-# WARNING send "Use send defined in \"Network.Socket.ByteString\"" #-}+{-# DEPRECATED send "Use send defined in \"Network.Socket.ByteString\"" #-} send :: Socket -- Bound/Connected Socket -> String -- Data to send -> IO Int -- Number of Bytes sent@@ -780,11 +829,11 @@ -- closed its half side of the connection. -- -- Receiving data from closed socket may lead to undefined behaviour.-{-# WARNING recv "Use recv defined in \"Network.Socket.ByteString\"" #-}+{-# DEPRECATED recv "Use recv defined in \"Network.Socket.ByteString\"" #-} recv :: Socket -> Int -> IO String recv sock l = fst <$> recvLen sock l -{-# WARNING recvLen "Use recv defined in \"Network.Socket.ByteString\" with \"Data.Bytestring.length\"" #-}+{-# DEPRECATED recvLen "Use recv defined in \"Network.Socket.ByteString\" with \"Data.Bytestring.length\"" #-} recvLen :: Socket -> Int -> IO (String, Int) recvLen sock nbytes = allocaBytes nbytes $ \ptr -> do@@ -1046,7 +1095,36 @@ fromIntegral `liftM` peek ptr_v +-- | Getting process ID, user ID and group ID for UNIX-domain sockets.+--+-- This is implemented with SO_PEERCRED on Linux and getpeereid()+-- on BSD variants. Unfortunately, on some BSD variants+-- getpeereid() returns unexpected results, rather than an error,+-- for AF_INET sockets. It is the user's responsibility to make sure+-- that the socket is a UNIX-domain socket.+-- Also, on some BSD variants, getpeereid() does not return credentials+-- for sockets created via 'socketPair', only separately created and then+-- explicitly connected UNIX-domain sockets work on such systems.+--+-- Since 2.7.0.0.+getPeerCredential :: Socket -> IO (Maybe CUInt, Maybe CUInt, Maybe CUInt)+#ifdef HAVE_STRUCT_UCRED+getPeerCredential sock = do+ (pid, uid, gid) <- getPeerCred sock+ if uid == maxBound then+ return (Nothing, Nothing, Nothing)+ else+ return (Just pid, Just uid, Just gid)+#elif defined(HAVE_GETPEEREID)+getPeerCredential sock = E.handle (\(E.SomeException _) -> return (Nothing,Nothing,Nothing)) $ do+ (uid, gid) <- getPeerEid sock+ return (Nothing, Just uid, Just gid)+#else+getPeerCredential _ = return (Nothing, Nothing, Nothing)+#endif+ #if defined(HAVE_STRUCT_UCRED) || defined(HAVE_GETPEEREID)+{-# DEPRECATED getPeerCred "Use getPeerCredential instead" #-} -- | Returns the processID, userID and groupID of the socket's peer. -- -- Only available on platforms that support SO_PEERCRED or GETPEEREID(3)@@ -1071,6 +1149,7 @@ #endif #ifdef HAVE_GETPEEREID+{-# DEPRECATED getPeerEid "Use getPeerCredential instead" #-} -- | The getpeereid() function returns the effective user and group IDs of the -- peer connected to a UNIX-domain socket getPeerEid :: Socket -> IO (CUInt, CUInt)@@ -1086,43 +1165,59 @@ #endif #endif +-- | Whether or not UNIX-domain sockets are available.+--+-- Since 3.0.0.0.+isUnixDomainSocketAvailable :: Bool+#if defined(DOMAIN_SOCKET_SUPPORT)+isUnixDomainSocketAvailable = True+#else+isUnixDomainSocketAvailable = False+#endif+ ##if !(MIN_VERSION_base(4,3,1)) closeFdWith closer fd = closer fd ##endif -#if defined(DOMAIN_SOCKET_SUPPORT) -- sending/receiving ancillary socket data; low-level mechanism -- for transmitting file descriptors, mainly. sendFd :: Socket -> CInt -> IO ()+#if defined(DOMAIN_SOCKET_SUPPORT) sendFd sock outfd = do- _ <- ($) throwSocketErrorWaitWrite sock "Network.Socket.sendFd" $- c_sendFd (fdSocket sock) outfd- -- Note: If Winsock supported FD-passing, thi would have been- -- incorrect (since socket FDs need to be closed via closesocket().)- closeFd outfd+ _ <- throwSocketErrorWaitWrite sock "Network.Socket.sendFd" $ c_sendFd (fdSocket sock) outfd+ return ()+foreign import ccall SAFE_ON_WIN "sendFd" c_sendFd :: CInt -> CInt -> IO CInt+#else+sendFd _ _ = error "Network.Socket.sendFd"+#endif -- | Receive a file descriptor over a domain socket. Note that the resulting -- file descriptor may have to be put into non-blocking mode in order to be -- used safely. See 'setNonBlockIfNeeded'. recvFd :: Socket -> IO CInt+#if defined(DOMAIN_SOCKET_SUPPORT) recvFd sock = do theFd <- throwSocketErrorWaitRead sock "Network.Socket.recvFd" $ c_recvFd (fdSocket sock) return theFd--foreign import ccall SAFE_ON_WIN "sendFd" c_sendFd :: CInt -> CInt -> IO CInt foreign import ccall SAFE_ON_WIN "recvFd" c_recvFd :: CInt -> IO CInt-+#else+recvFd _ = error "Network.Socket.recvFd" #endif -- --------------------------------------------------------------------------- -- Utility Functions +{-# DEPRECATED aNY_PORT "Use defaultPort instead" #-} aNY_PORT :: PortNumber aNY_PORT = 0 +defaultPort :: PortNumber+defaultPort = 0+ -- | The IPv4 wild card address. +{-# DEPRECATED iNADDR_ANY "Use getAddrInfo instead" #-} iNADDR_ANY :: HostAddress iNADDR_ANY = htonl (#const INADDR_ANY) @@ -1131,20 +1226,27 @@ -- | 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" #-}+ #if defined(IPV6_SOCKET_SUPPORT) -- | The IPv6 wild card address. +{-# DEPRECATED iN6ADDR_ANY "Use getAddrInfo instead" #-} iN6ADDR_ANY :: HostAddress6 iN6ADDR_ANY = (0, 0, 0, 0) #endif +{-# DEPRECATED sOMAXCONN "Use maxListenQueue instead" #-} sOMAXCONN :: Int sOMAXCONN = #const SOMAXCONN +{-# DEPRECATED sOL_SOCKET "This is not necessary anymore" #-} sOL_SOCKET :: Int sOL_SOCKET = #const SOL_SOCKET #ifdef SCM_RIGHTS+{-# DEPRECATED sCM_RIGHTS "This is not necessary anymore" #-} sCM_RIGHTS :: Int sCM_RIGHTS = #const SCM_RIGHTS #endif@@ -1203,6 +1305,7 @@ isConnected (MkSocket _ _ _ _ status) = do value <- readMVar status return (value == Connected)+{-# DEPRECATED isConnected "SocketStatus will be removed" #-} -- ----------------------------------------------------------------------------- -- Socket Predicates@@ -1211,19 +1314,23 @@ isBound (MkSocket _ _ _ _ status) = do value <- readMVar status return (value == Bound)+{-# DEPRECATED isBound "SocketStatus will be removed" #-} isListening :: Socket -> IO Bool isListening (MkSocket _ _ _ _ status) = do value <- readMVar status return (value == Listening)+{-# DEPRECATED isListening "SocketStatus will be removed" #-} isReadable :: Socket -> IO Bool isReadable (MkSocket _ _ _ _ status) = do value <- readMVar status return (value == Listening || value == Connected)+{-# DEPRECATED isReadable "SocketStatus will be removed" #-} isWritable :: Socket -> IO Bool isWritable = isReadable -- sort of.+{-# DEPRECATED isWritable "SocketStatus will be removed" #-} isAcceptable :: Family -> SocketType -> SocketStatus -> Bool #if defined(DOMAIN_SOCKET_SUPPORT)@@ -1233,10 +1340,12 @@ isAcceptable AF_UNIX _ _ = False #endif isAcceptable _ _ status = status == Connected || status == Listening+{-# DEPRECATED isAcceptable "SocketStatus will be removed" #-} -- ----------------------------------------------------------------------------- -- Internet address manipulation routines: +{-# DEPRECATED inet_addr "Use \"getNameInfo\" instead" #-} inet_addr :: String -> IO HostAddress inet_addr ipstr = withSocketsDo $ do withCString ipstr $ \str -> do@@ -1246,6 +1355,7 @@ "Network.Socket.inet_addr: Malformed address: " ++ ipstr else return had -- network byte order +{-# DEPRECATED inet_ntoa "Use \"getNameInfo\" instead" #-} inet_ntoa :: HostAddress -> IO String inet_ntoa haddr = withSocketsDo $ do pstr <- c_inet_ntoa haddr@@ -1323,8 +1433,8 @@ | AI_NUMERICSERV -- | If no 'HostName' value is provided, the network -- address in each 'SockAddr'- -- will be left as a "wild card", i.e. as either 'iNADDR_ANY'- -- or 'iN6ADDR_ANY'. This is useful for server applications that+ -- will be left as a "wild card".+ -- This is useful for server applications that -- will accept connections from any client. | AI_PASSIVE -- | If an IPv6 lookup is performed, and no IPv6@@ -1758,32 +1868,55 @@ sClose :: Socket -> IO () sClose = close -{-# DEPRECATED sIsConnected "use 'isConnected'" #-}+{-# DEPRECATED sIsConnected "SocketStatus will be removed" #-} --- | Deprecated alias for 'isConnected'. sIsConnected :: Socket -> IO Bool sIsConnected = isConnected -{-# DEPRECATED sIsBound "use 'isBound'" #-}+{-# DEPRECATED sIsBound "SocketStatus will be removed" #-} --- | Deprecated alias for 'isBound'. sIsBound :: Socket -> IO Bool sIsBound = isBound -{-# DEPRECATED sIsListening "use 'isListening'" #-}+{-# DEPRECATED sIsListening "SocketStatus will be removed" #-} --- | Deprecated alias for 'isListening'. sIsListening :: Socket -> IO Bool sIsListening = isListening -{-# DEPRECATED sIsReadable "use 'isReadable'" #-}+{-# DEPRECATED sIsReadable "SocketStatus will be removed" #-} --- | Deprecated alias for 'isReadable'. sIsReadable :: Socket -> IO Bool sIsReadable = isReadable -{-# DEPRECATED sIsWritable "use 'isWritable'" #-}+{-# DEPRECATED sIsWritable "SocketStatus will be removed" #-} --- | Deprecated alias for 'isWritable'. sIsWritable :: Socket -> IO Bool sIsWritable = isWritable++#if defined(HAVE_IF_NAMETOINDEX)+-- | Returns the index corresponding to the interface name.+--+-- Since 2.7.0.0.+ifNameToIndex :: String -> IO (Maybe Int)+ifNameToIndex ifname = do+ index <- withCString ifname c_if_nametoindex+ -- On failure zero is returned. We'll return Nothing.+ return $ if index == 0 then Nothing else Just $ fromIntegral index++-- | Returns the interface name corresponding to the index.+--+-- Since 2.7.0.0.+ifIndexToName :: Int -> IO (Maybe String)+ifIndexToName ifn = allocaBytes 16 $ \ptr -> do -- 16 == IFNAMSIZ+ r <- c_if_indextoname (fromIntegral ifn) ptr+ if r == nullPtr then+ return Nothing+ else+ Just <$> peekCString ptr++foreign import CALLCONV safe "if_nametoindex"+ c_if_nametoindex :: CString -> IO CUInt++foreign import CALLCONV safe "if_indextoname"+ c_if_indextoname :: CUInt -> CString -> IO CString+#endif
Network/Socket/ByteString.hsc view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} {-# LANGUAGE CPP, ForeignFunctionInterface #-} #include "HsNet.h"@@ -263,7 +264,7 @@ -- | @withIOVec cs f@ executes the computation @f@, passing as argument a pair -- consisting of a pointer to a temporarily allocated array of pointers to--- 'IOVec' made from @cs@ and the number of pointers (@length cs@).+-- IOVec made from @cs@ and the number of pointers (@length cs@). -- /Unix only/. withIOVec :: [ByteString] -> ((Ptr IOVec, Int) -> IO a) -> IO a withIOVec cs f =
Network/Socket/ByteString/Lazy/Posix.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} {-# LANGUAGE BangPatterns #-} module Network.Socket.ByteString.Lazy.Posix (
Network/Socket/Types.hsc view
@@ -72,18 +72,7 @@ import Foreign.Ptr import Foreign.Storable --- | Represents a socket. The fields are, respectively:------ * File descriptor--- * Socket family--- * Socket type--- * Protocol number--- * Status flag------ If you are calling the 'MkSocket' constructor directly you should ensure--- you have called 'Network.withSocketsDo' and that the file descriptor is--- in non-blocking mode. See 'Network.Socket.setNonBlockIfNeeded'.---+-- | A socket data type. -- 'Socket's are not GCed unless they are closed by 'close'. data Socket = MkSocket@@ -94,6 +83,8 @@ (MVar SocketStatus) -- Status Flag deriving Typeable +{-# DEPRECATED MkSocket "'MkSocket' will not be available in version 3.0.0.0 or later. Use fdSocket instead" #-}+ sockFd :: Socket -> CInt sockFd (MkSocket n _ _ _ _) = n @@ -133,6 +124,8 @@ | Closed -- ^ Closed was closed by 'close' deriving (Eq, Show, Typeable) +{-# DEPRECATED SocketStatus "SocketStatus will be removed" #-}+ ----------------------------------------------------------------------------- -- Socket types @@ -191,6 +184,8 @@ #endif _ -> Nothing +{-# DEPRECATED packSocketType "packSocketType will not be available in version 3.0.0.0 or later." #-}+ packSocketType :: SocketType -> CInt packSocketType stype = fromMaybe (error errMsg) (packSocketType' stype) where@@ -310,6 +305,8 @@ | AF_CAN -- Controller Area Network deriving (Eq, Ord, Read, Show) +{-# DEPRECATED packFamily "packFamily will not be available in version 3.0.0.0 or later." #-}+ packFamily :: Family -> CInt packFamily f = case packFamily' f of Just fam -> fam@@ -526,6 +523,8 @@ --------- ---------- +{-# DEPRECATED unpackFamily "unpackFamily will not be available in version 3.0.0.0 or later." #-}+ unpackFamily :: CInt -> Family unpackFamily f = case f of (#const AF_UNSPEC) -> AF_UNSPEC@@ -807,11 +806,11 @@ -- 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.+-- 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. Currently only UNIX-domain sockets and the Internet -- families are supported. #if defined(IPV6_SOCKET_SUPPORT)
configure.ac view
@@ -1,4 +1,4 @@-AC_INIT([Haskell network package], [2.6.3.6], [libraries@haskell.org], [network])+AC_INIT([Haskell network package], [2.7.0.0], [libraries@haskell.org], [network]) ac_includes_default="$ac_includes_default #ifdef HAVE_SYS_SOCKET_H@@ -101,7 +101,7 @@ fi dnl ---------------------------------------------------dnl * test for GETPEEREID(3)+dnl * test for GETPEEREID(3) dnl -------------------------------------------------- AC_MSG_CHECKING(for getpeereid in unistd.h) AC_CHECK_FUNC( getpeereid, AC_DEFINE([HAVE_GETPEEREID], [1], [Define to 1 if you have getpeereid.] ))
examples/EchoServer.hs view
@@ -23,6 +23,10 @@ open addr = do sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) setSocketOption sock ReuseAddr 1+ -- If the prefork technique is not used,+ -- set CloseOnExec for the security reasons.+ let fd = fdSocket sock+ setCloseOnExecIfNeeded fd bind sock (addrAddress addr) listen sock 10 return sock
network.cabal view
@@ -1,5 +1,5 @@ name: network-version: 2.6.3.6+version: 2.7.0.0 license: BSD3 license-file: LICENSE maintainer: Kazu Yamamoto, Evan Borden@@ -84,6 +84,7 @@ build-depends: base < 5, bytestring,+ directory, HUnit, network, hspec
tests/SimpleSpec.hs view
@@ -13,6 +13,7 @@ import qualified Data.ByteString.Char8 as C import Network.Socket hiding (send, sendTo, recv, recvFrom) import Network.Socket.ByteString+import System.Directory import System.Timeout (timeout) import Test.Hspec@@ -119,6 +120,44 @@ getSocketOption sock UserTimeout `shouldReturn` 2000 close sock + -- On various BSD systems the peer credentials are exchanged during+ -- connect(), and this does not happen with `socketpair()`. Therefore,+ -- we must actually set up a listener and connect, rather than use a+ -- socketpair().+ --+ describe "getPeerCredential" $ do+ it "can return something" $ do+ when isUnixDomainSocketAvailable $ do+ -- It would be useful to check that we did not get garbage+ -- back, but rather the actual uid of the test program. For+ -- that we'd need System.Posix.User, but that is not available+ -- under Windows. For now, accept the risk that we did not get+ -- the right answer.+ --+ let client sock = do+ (_, uid, _) <- getPeerCredential sock+ uid `shouldNotBe` Nothing+ server (sock, _) = do+ (_, uid, _) <- getPeerCredential sock+ uid `shouldNotBe` Nothing+ unixTest client server+ {- The below test fails on many *BSD systems, because the getsockopt()+ call that underlies getpeereid() does not have the same meaning for+ all address families, but the C-library was not checking that the+ provided sock is an AF_UNIX socket. This will fixed some day, but+ we should not fail on those systems in the mean-time. The upstream+ C-library fix is to call getsockname() and check the address family+ before calling `getpeereid()`. We could duplicate that in our own+ code, and then this test would work on those platforms that have+ `getpeereid()` and not the SO_PEERCRED socket option.++ it "return nothing for non-UNIX-domain socket" $ do+ when isUnixDomainSocketAvailable $ do+ s <- socket AF_INET Stream defaultProtocol+ cred1 <- getPeerCredential s+ cred1 `shouldBe` (Nothing,Nothing,Nothing)+ -}+ describe "getAddrInfo" $ do it "works for IPv4 address" $ do let hints = defaultHints { addrFlags = [AI_NUMERICHOST, AI_ADDRCONFIG] }@@ -143,12 +182,47 @@ testMsg :: ByteString testMsg = "This is a test message." +unixAddr :: String+unixAddr = "/tmp/network-test"+ ------------------------------------------------------------------------ -- Test helpers -- | Establish a connection between client and server and then run -- 'clientAct' and 'serverAct', in different threads. Both actions -- get passed a connected 'Socket', used for communicating between+-- client and server. 'unixTest' makes sure that the 'Socket' is+-- closed after the actions have run.+unixTest :: (Socket -> IO a) -> ((Socket, SockAddr) -> IO b) -> IO ()+unixTest clientAct serverAct = do+ test clientSetup clientAct serverSetup server+ where+ clientSetup = do+ sock <- socket AF_UNIX Stream defaultProtocol+ connect sock (SockAddrUnix unixAddr)+ return sock++ serverSetup = do+ sock <- socket AF_UNIX Stream defaultProtocol+ unlink unixAddr -- just in case+ bind sock (SockAddrUnix unixAddr)+ listen sock 1+ return sock++ server sock = E.bracket (accept sock) (killClientSock . fst) serverAct++ unlink file = do+ exist <- doesFileExist file+ when exist $ removeFile file++ killClientSock sock = do+ shutdown sock ShutdownBoth+ close sock+ unlink unixAddr++-- | Establish a connection between client and server and then run+-- 'clientAct' and 'serverAct', in different threads. Both actions+-- get passed a connected 'Socket', used for communicating between -- client and server. 'tcpTest' makes sure that the 'Socket' is -- closed after the actions have run. tcpTest :: (Socket -> IO a) -> (Socket -> IO b) -> IO ()@@ -161,6 +235,11 @@ serverPort <- readMVar portVar addr:_ <- getAddrInfo (Just hints) (Just serverAddr) (Just $ show serverPort) sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+#if !defined(mingw32_HOST_OS)+ let fd = fdSocket sock+ getNonBlock fd `shouldReturn` True+ getCloseOnExec fd `shouldReturn` False+#endif connect sock $ addrAddress addr return sock @@ -171,7 +250,16 @@ } addr:_ <- getAddrInfo (Just hints) (Just serverAddr) Nothing sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+ let fd = fdSocket sock+#if !defined(mingw32_HOST_OS)+ getNonBlock fd `shouldReturn` True+ getCloseOnExec fd `shouldReturn` False+#endif setSocketOption sock ReuseAddr 1+ setCloseOnExecIfNeeded fd+#if !defined(mingw32_HOST_OS)+ getCloseOnExec fd `shouldReturn` True+#endif bind sock $ addrAddress addr listen sock 1 serverPort <- socketPort sock@@ -180,6 +268,11 @@ server sock = do (clientSock, _) <- accept sock+#if !defined(mingw32_HOST_OS)+ let fd = fdSocket clientSock+ getNonBlock fd `shouldReturn` True+ getCloseOnExec fd `shouldReturn` True+#endif _ <- serverAct clientSock close clientSock