network 2.6.3.3 → 2.6.3.4
raw patch · 15 files changed
+302/−333 lines, 15 filesdep +directory
Dependencies added: directory
Files
- CHANGELOG.md +9/−1
- Network.hs +3/−2
- Network/Socket.hsc +98/−35
- Network/Socket/ByteString.hsc +2/−61
- Network/Socket/Internal.hsc +4/−2
- Network/Socket/Types.hsc +12/−4
- configure.ac +1/−1
- examples/EchoClient.hs +21/−12
- examples/EchoServer.hs +31/−21
- include/HsNetworkConfig.h +0/−178
- network.buildinfo.in +1/−0
- network.cabal +11/−16
- tests/BadFileDescriptor.hs +51/−0
- tests/Regression.hs +1/−0
- tests/Simple.hs +57/−0
CHANGELOG.md view
@@ -1,7 +1,15 @@+## Version 2.6.3.4++ * Don't touch IPv6Only when running on OpenBSD+ [#227](https://github.com/haskell/network/pull/227)+ * Do not closeFd within sendFd+ [#271](https://github.com/haskell/network/pull/271)+ * Updating examples and docs.+ ## Version 2.6.3.3 * Adds a function to show the defaultHints without reading their undefined fields- [#291](https://github.com/haskell/network/pull/292)+ [#291](https://github.com/haskell/network/pull/291) * Improve exception error messages for getAddrInfo and getNameInfo [#289](https://github.com/haskell/network/pull/289) * Deprecating SockAddrCan.
Network.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} ----------------------------------------------------------------------------- -- | -- Module : Network@@ -431,10 +432,10 @@ {-$buffering -The 'Handle' returned by 'connectTo' and 'accept' is block-buffered by+The 'Handle' returned by 'connectTo' and 'accept' is 'NoBuffering' by default. For an interactive application you may want to set the buffering mode on the 'Handle' to-'LineBuffering' or 'NoBuffering', like so:+'LineBuffering' or 'BlockBuffering', like so: > h <- connectTo host port > hSetBuffering h LineBuffering
Network/Socket.hsc view
@@ -18,6 +18,75 @@ -- A higher level interface to networking operations is provided -- through the module "Network". --+-- Here are two minimal example programs using the TCP/IP protocol: a+-- server that echoes all data that it receives back (servicing only+-- one client) and a client using it.+--+-- > -- Echo server program+-- > module Main (main) where+-- >+-- > import Control.Concurrent (forkFinally)+-- > import qualified Control.Exception as E+-- > import Control.Monad (unless, forever, void)+-- > import qualified Data.ByteString as S+-- > import Network.Socket hiding (recv)+-- > import Network.Socket.ByteString (recv, sendAll)+-- >+-- > main :: IO ()+-- > main = withSocketsDo $ do+-- > addr <- resolve "3000"+-- > E.bracket (open addr) close loop+-- > where+-- > resolve port = do+-- > let hints = defaultHints {+-- > addrFlags = [AI_PASSIVE]+-- > , addrSocketType = Stream+-- > }+-- > addr:_ <- getAddrInfo (Just hints) Nothing (Just port)+-- > return addr+-- > open addr = do+-- > sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+-- > setSocketOption sock ReuseAddr 1+-- > bind sock (addrAddress addr)+-- > listen sock 10+-- > return sock+-- > loop sock = forever $ do+-- > (conn, peer) <- accept sock+-- > putStrLn $ "Connection from " ++ show peer+-- > void $ forkFinally (talk conn) (\_ -> close conn)+-- > talk conn = do+-- > msg <- recv conn 1024+-- > unless (S.null msg) $ do+-- > sendAll conn msg+-- > talk conn+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- > -- Echo client program+-- > module Main (main) where+-- >+-- > import qualified Control.Exception as E+-- > import qualified Data.ByteString.Char8 as C+-- > import Network.Socket hiding (recv)+-- > import Network.Socket.ByteString (recv, sendAll)+-- >+-- > main :: IO ()+-- > main = withSocketsDo $ do+-- > addr <- resolve "127.0.0.1" "3000"+-- > E.bracket (open addr) close talk+-- > where+-- > resolve host port = do+-- > let hints = defaultHints { addrSocketType = Stream }+-- > addr:_ <- getAddrInfo (Just hints) (Just host) (Just port)+-- > return addr+-- > open addr = do+-- > sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+-- > connect sock $ addrAddress addr+-- > return sock+-- > talk sock = do+-- > sendAll sock "Hello, world!"+-- > msg <- recv sock 1024+-- > putStr "Received: "+-- > C.putStrLn msg ----------------------------------------------------------------------------- #include "HsNet.h"@@ -204,7 +273,10 @@ import Data.Typeable import System.IO.Error -import GHC.Conc (threadWaitRead, threadWaitWrite)+import GHC.Conc (threadWaitWrite)+# ifdef HAVE_ACCEPT4+import GHC.Conc (threadWaitRead)+# endif ##if MIN_VERSION_base(4,3,1) import GHC.Conc (closeFdWith) ##endif@@ -276,8 +348,7 @@ mkSocket fd fam sType pNum stat = do mStat <- newMVar stat withSocketsDo $ return ()- return (MkSocket fd fam sType pNum mStat)-+ return $ MkSocket fd fam sType pNum mStat fdSocket :: Socket -> CInt fdSocket (MkSocket fd _ _ _ _) = fd@@ -309,6 +380,10 @@ #if defined(CAN_SOCKET_SUPPORT) showsPrec _ (SockAddrCan ifidx) = shows ifidx #endif+#if !(defined(IPV6_SOCKET_SUPPORT) \+ && defined(DOMAIN_SOCKET_SUPPORT) && defined(CAN_SOCKET_SUPPORT))+ showsPrec _ _ = error "showsPrec: not supported"+#endif ----------------------------------------------------------------------------- -- Connection Functions@@ -347,9 +422,7 @@ fd <- throwSocketErrorIfMinus1Retry "Network.Socket.socket" $ c_socket (packFamily family) c_stype protocol setNonBlockIfNeeded fd- socket_status <- newMVar NotConnected- withSocketsDo $ return ()- let sock = MkSocket fd family stype protocol socket_status+ sock <- mkSocket fd family stype protocol NotConnected #if HAVE_DECL_IPV6_V6ONLY -- The default value of the IPv6Only option is platform specific, -- so we explicitly set it to 0 to provide a common default.@@ -358,7 +431,7 @@ -- so trying to change it might throw an error. when (family == AF_INET6 && (stype == Stream || stype == Datagram)) $ E.catch (setSocketOption sock IPv6Only 0) $ (\(_ :: E.IOException) -> return ())-# else+# elif !defined(__OpenBSD__) when (family == AF_INET6 && (stype == Stream || stype == Datagram)) $ setSocketOption sock IPv6Only 0 `onException` close sock # endif@@ -386,9 +459,7 @@ where mkNonBlockingSocket fd = do setNonBlockIfNeeded fd- stat <- newMVar Connected- withSocketsDo $ return ()- return (MkSocket fd family stype protocol stat)+ mkSocket fd family stype protocol Connected foreign import ccall unsafe "socketpair" c_socketpair :: CInt -> CInt -> CInt -> Ptr CInt -> IO CInt@@ -507,10 +578,8 @@ -> IO (Socket, -- Readable Socket SockAddr) -- Peer details -accept sock@(MkSocket s family stype protocol status) = do- currentStatus <- readMVar status- okay <- isAcceptable sock- if not okay+accept sock@(MkSocket s family stype protocol status) = withMVar status $ \currentStatus -> do+ if not $ isAcceptable family stype currentStatus then ioError $ userError $ "Network.Socket.accept: can't accept socket (" ++@@ -546,8 +615,8 @@ # endif /* HAVE_ACCEPT4 */ #endif addr <- peekSockAddr sockaddr- new_status <- newMVar Connected- return ((MkSocket new_sock family stype protocol new_status), addr)+ sock' <- mkSocket new_sock family stype protocol Connected+ return (sock', addr) #if defined(mingw32_HOST_OS) foreign import ccall unsafe "HsNet.h acceptNewSock"@@ -601,7 +670,7 @@ sendBufTo sock@(MkSocket s _family _stype _protocol _status) ptr nbytes addr = do withSockAddr addr $ \p_addr sz -> do liftM fromIntegral $- throwSocketErrorWaitWrite sock "Network.Socket.sendTo" $+ throwSocketErrorWaitWrite sock "Network.Socket.sendBufTo" $ c_sendto s ptr (fromIntegral $ nbytes) 0{-flags-} p_addr (fromIntegral sz) @@ -631,12 +700,12 @@ -- GHC ticket #1129) recvBufFrom :: Socket -> Ptr a -> Int -> IO (Int, SockAddr) recvBufFrom sock@(MkSocket s family _stype _protocol _status) ptr nbytes- | nbytes <= 0 = ioError (mkInvalidRecvArgError "Network.Socket.recvFrom")+ | nbytes <= 0 = ioError (mkInvalidRecvArgError "Network.Socket.recvBufFrom") | otherwise = withNewSockAddr family $ \ptr_addr sz -> do alloca $ \ptr_len -> do poke ptr_len (fromIntegral sz)- len <- throwSocketErrorWaitRead sock "Network.Socket.recvFrom" $+ len <- throwSocketErrorWaitRead sock "Network.Socket.recvBufFrom" $ c_recvfrom s ptr (fromIntegral nbytes) 0{-flags-} ptr_addr ptr_len let len' = fromIntegral len@@ -714,7 +783,7 @@ recv :: Socket -> Int -> IO String recv sock l = fst <$> recvLen sock l -{-# WARNING recvLen "Use recvLen defined in \"Network.Socket.ByteString\"" #-}+{-# WARNING 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@@ -1025,11 +1094,8 @@ -- for transmitting file descriptors, mainly. sendFd :: Socket -> CInt -> IO () 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 () -- | 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@@ -1155,17 +1221,14 @@ isWritable :: Socket -> IO Bool isWritable = isReadable -- sort of. -isAcceptable :: Socket -> IO Bool+isAcceptable :: Family -> SocketType -> SocketStatus -> Bool #if defined(DOMAIN_SOCKET_SUPPORT)-isAcceptable (MkSocket _ AF_UNIX x _ status)- | x == Stream || x == SeqPacket = do- value <- readMVar status- return (value == Connected || value == Bound || value == Listening)-isAcceptable (MkSocket _ AF_UNIX _ _ _) = return False+isAcceptable AF_UNIX sockTyp status+ | sockTyp == Stream || sockTyp == SeqPacket =+ status == Connected || status == Bound || status == Listening+isAcceptable AF_UNIX _ _ = False #endif-isAcceptable (MkSocket _ _ _ _ status) = do- value <- readMVar status- return (value == Connected || value == Listening)+isAcceptable _ _ status = status == Connected || status == Listening -- ----------------------------------------------------------------------------- -- Internet address manipulation routines:@@ -1174,7 +1237,7 @@ inet_addr ipstr = withSocketsDo $ do withCString ipstr $ \str -> do had <- c_inet_addr str- if had == -1+ if had == maxBound then ioError $ userError $ "Network.Socket.inet_addr: Malformed address: " ++ ipstr else return had -- network byte order
Network/Socket/ByteString.hsc view
@@ -38,12 +38,9 @@ -- * Receive data from a socket , recv , recvFrom-- -- * Example- -- $example ) where -import Control.Exception (catch, throwIO)+import Control.Exception as E (catch, throwIO) import Control.Monad (when) import Data.ByteString (ByteString) import Data.ByteString.Internal (createAndTrim)@@ -226,7 +223,7 @@ recv sock nbytes | nbytes < 0 = ioError (mkInvalidRecvArgError "Network.Socket.ByteString.recv") | otherwise = createAndTrim nbytes $ \ptr ->- catch+ E.catch (recvBuf sock ptr nbytes) (\e -> if isEOFError e then return 0 else throwIO e) @@ -280,59 +277,3 @@ unsafeUseAsCStringLen s $ \(sPtr, sLen) -> poke ptr $ IOVec sPtr (fromIntegral sLen) #endif---- ------------------------------------------------------------------------ Example---- $example------ Here are two minimal example programs using the TCP/IP protocol: a--- server that echoes all data that it receives back (servicing only--- one client) and a client using it.------ > -- Echo server program--- > module Main where--- >--- > import Control.Monad (unless)--- > import Network.Socket hiding (recv)--- > import qualified Data.ByteString as S--- > import Network.Socket.ByteString (recv, sendAll)--- >--- > main :: IO ()--- > main = withSocketsDo $--- > do addrinfos <- getAddrInfo--- > (Just (defaultHints {addrFlags = [AI_PASSIVE]}))--- > Nothing (Just "3000")--- > let serveraddr = head addrinfos--- > sock <- socket (addrFamily serveraddr) Stream defaultProtocol--- > bind sock (addrAddress serveraddr)--- > listen sock 1--- > (conn, _) <- accept sock--- > talk conn--- > close conn--- > close sock--- >--- > where--- > talk :: Socket -> IO ()--- > talk conn =--- > do msg <- recv conn 1024--- > unless (S.null msg) $ sendAll conn msg >> talk conn------ > -- Echo client program--- > module Main where--- >--- > import Network.Socket hiding (recv)--- > import Network.Socket.ByteString (recv, sendAll)--- > import qualified Data.ByteString.Char8 as C--- >--- > main :: IO ()--- > main = withSocketsDo $--- > do addrinfos <- getAddrInfo Nothing (Just "") (Just "3000")--- > let serveraddr = head addrinfos--- > sock <- socket (addrFamily serveraddr) Stream defaultProtocol--- > connect sock (addrAddress serveraddr)--- > sendAll sock $ C.pack "Hello, world!"--- > msg <- recv sock 1024--- > close sock--- > putStr "Received "--- > C.putStrLn msg
Network/Socket/Internal.hsc view
@@ -239,7 +239,8 @@ -- --------------------------------------------------------------------------- -- WinSock support -{-| With older versions of the @network@ library on Windows operating systems,+{-| With older versions of the @network@ library (version 2.6.0.2 or earlier)+on Windows operating systems, the networking subsystem must be initialised using 'withSocketsDo' before any networking operations can be used. eg. @@ -248,7 +249,8 @@ It is fine to nest calls to 'withSocketsDo', and to perform networking operations after 'withSocketsDo' has returned. -In newer versions of the @network@ library it is only necessary to call+In newer versions of the @network@ library (version v2.6.1.0 or later)+it is only necessary to call 'withSocketsDo' if you are calling the 'MkSocket' constructor directly. However, for compatibility with older versions on Windows, it is good practice to always call 'withSocketsDo' (it's very cheap).
Network/Socket/Types.hsc view
@@ -83,6 +83,8 @@ -- 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'.+--+-- 'Socket's are not GCed unless they are closed by 'close'. data Socket = MkSocket CInt -- File Descriptor@@ -258,7 +260,7 @@ | AF_LAT -- LAT | AF_HYLINK -- NSC Hyperchannel | AF_APPLETALK -- Apple Talk- | AF_ROUTE -- Internal Routing Protocol+ | AF_ROUTE -- Internal Routing Protocol (aka AF_NETLINK) | AF_NETBIOS -- NetBios-style addresses | AF_NIT -- Network Interface Tap | AF_802 -- IEEE 802.2, also ISO 8802@@ -854,9 +856,7 @@ _ -> False #endif -#if defined(CAN_SOCKET_SUPPORT)-{-# DEPRECATED SockAddrCan "This will be removed in 2.7" #-}-#endif+{-# DEPRECATED SockAddrCan "This will be removed in 3.0" #-} #if defined(WITH_WINSOCK) type CSaFamily = (#type unsigned short)@@ -883,6 +883,10 @@ #if defined(CAN_SOCKET_SUPPORT) sizeOfSockAddr (SockAddrCan _) = #const sizeof(struct sockaddr_can) #endif+#if !(defined(IPV6_SOCKET_SUPPORT) \+ && defined(DOMAIN_SOCKET_SUPPORT) && defined(CAN_SOCKET_SUPPORT))+sizeOfSockAddr _ = error "sizeOfSockAddr: not supported"+#endif -- | Computes the storage requirements (in bytes) required for a -- 'SockAddr' with the given 'Family'.@@ -971,6 +975,10 @@ zeroMemory p (#const sizeof(struct sockaddr_can)) #endif (#poke struct sockaddr_can, can_ifindex) p ifIndex+#endif+#if !(defined(IPV6_SOCKET_SUPPORT) \+ && defined(DOMAIN_SOCKET_SUPPORT) && defined(CAN_SOCKET_SUPPORT))+pokeSockAddr _ _ = error "pokeSockAddr: not supported" #endif -- | Read a 'SockAddr' from the given memory location.
configure.ac view
@@ -1,4 +1,4 @@-AC_INIT([Haskell network package], [2.6.3.3], [libraries@haskell.org], [network])+AC_INIT([Haskell network package], [2.6.3.4], [libraries@haskell.org], [network]) ac_includes_default="$ac_includes_default #ifdef HAVE_SYS_SOCKET_H
examples/EchoClient.hs view
@@ -1,18 +1,27 @@+{-# LANGUAGE OverloadedStrings #-} -- Echo client program-module Main where+module Main (main) where +import qualified Control.Exception as E+import qualified Data.ByteString.Char8 as C import Network.Socket hiding (recv) import Network.Socket.ByteString (recv, sendAll)-import qualified Data.ByteString.Char8 as C main :: IO ()-main = withSocketsDo $- do addrinfos <- getAddrInfo Nothing (Just "") (Just "3000")- let serveraddr = head addrinfos- sock <- socket (addrFamily serveraddr) Stream defaultProtocol- connect sock (addrAddress serveraddr)- sendAll sock $ C.pack "Hello, world!"- msg <- recv sock 1024- close sock- putStr "Received "- C.putStrLn msg+main = withSocketsDo $ do+ addr <- resolve "127.0.0.1" "3000"+ E.bracket (open addr) close talk+ where+ resolve host port = do+ let hints = defaultHints { addrSocketType = Stream }+ addr:_ <- getAddrInfo (Just hints) (Just host) (Just port)+ return addr+ open addr = do+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+ connect sock $ addrAddress addr+ return sock+ talk sock = do+ sendAll sock "Hello, world!"+ msg <- recv sock 1024+ putStr "Received: "+ C.putStrLn msg
examples/EchoServer.hs view
@@ -1,27 +1,37 @@ -- Echo server program-module Main where+module Main (main) where -import Control.Monad (unless)-import Network.Socket hiding (recv)+import Control.Concurrent (forkFinally)+import qualified Control.Exception as E+import Control.Monad (unless, forever, void) import qualified Data.ByteString as S+import Network.Socket hiding (recv) import Network.Socket.ByteString (recv, sendAll) main :: IO ()-main = withSocketsDo $- do addrinfos <- getAddrInfo- (Just (defaultHints {addrFlags = [AI_PASSIVE]}))- Nothing (Just "3000")- let serveraddr = head addrinfos- sock <- socket (addrFamily serveraddr) Stream defaultProtocol- bind sock (addrAddress serveraddr)- listen sock 1- (conn, _) <- accept sock- talk conn- close conn- close sock-- where- talk :: Socket -> IO ()- talk conn =- do msg <- recv conn 1024- unless (S.null msg) $ sendAll conn msg >> talk conn+main = withSocketsDo $ do+ addr <- resolve "3000"+ E.bracket (open addr) close loop+ where+ resolve port = do+ let hints = defaultHints {+ addrFlags = [AI_PASSIVE]+ , addrSocketType = Stream+ }+ addr:_ <- getAddrInfo (Just hints) Nothing (Just port)+ return addr+ open addr = do+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+ setSocketOption sock ReuseAddr 1+ bind sock (addrAddress addr)+ listen sock 10+ return sock+ loop sock = forever $ do+ (conn, peer) <- accept sock+ putStrLn $ "Connection from " ++ show peer+ void $ forkFinally (talk conn) (\_ -> close conn)+ talk conn = do+ msg <- recv conn 1024+ unless (S.null msg) $ do+ sendAll conn msg+ talk conn
− include/HsNetworkConfig.h
@@ -1,178 +0,0 @@-/* include/HsNetworkConfig.h. Generated from HsNetworkConfig.h.in by configure. */-/* include/HsNetworkConfig.h.in. Generated from configure.ac by autoheader. */--/* Define to 1 if you have the `accept4' function. */-#define HAVE_ACCEPT4 1--/* Define to 1 if you have the <arpa/inet.h> header file. */-#define HAVE_ARPA_INET_H 1--/* Define to 1 if you have a BSDish sendfile(2) implementation. */-/* #undef HAVE_BSD_SENDFILE */--/* Define to 1 if you have the declaration of `AI_ADDRCONFIG', and to 0 if you- don't. */-#define HAVE_DECL_AI_ADDRCONFIG 1--/* Define to 1 if you have the declaration of `AI_ALL', and to 0 if you don't.- */-#define HAVE_DECL_AI_ALL 1--/* Define to 1 if you have the declaration of `AI_NUMERICSERV', and to 0 if- you don't. */-#define HAVE_DECL_AI_NUMERICSERV 1--/* Define to 1 if you have the declaration of `AI_V4MAPPED', and to 0 if you- don't. */-#define HAVE_DECL_AI_V4MAPPED 1--/* Define to 1 if you have the declaration of `IPPROTO_IP', and to 0 if you- don't. */-#define HAVE_DECL_IPPROTO_IP 1--/* Define to 1 if you have the declaration of `IPPROTO_IPV6', and to 0 if you- don't. */-#define HAVE_DECL_IPPROTO_IPV6 1--/* Define to 1 if you have the declaration of `IPPROTO_TCP', and to 0 if you- don't. */-#define HAVE_DECL_IPPROTO_TCP 1--/* Define to 1 if you have the declaration of `IPV6_V6ONLY', and to 0 if you- don't. */-#define HAVE_DECL_IPV6_V6ONLY 1--/* Define to 1 if you have the <fcntl.h> header file. */-#define HAVE_FCNTL_H 1--/* Define to 1 if you have the `gai_strerror' function. */-#define HAVE_GAI_STRERROR 1--/* Define to 1 if you have the `getaddrinfo' function. */-#define HAVE_GETADDRINFO 1--/* Define to 1 if you have the `gethostent' function. */-#define HAVE_GETHOSTENT 1--/* Define to 1 if you have getpeereid. */-/* #undef HAVE_GETPEEREID */--/* Define to 1 if you have the `if_nametoindex' function. */-#define HAVE_IF_NAMETOINDEX 1--/* Define to 1 if you have the <inttypes.h> header file. */-#define HAVE_INTTYPES_H 1--/* Define to 1 if in_addr_t is available. */-#define HAVE_IN_ADDR_T 1--/* Define to 1 if you have the `ws2_32' library (-lws2_32). */-/* #undef HAVE_LIBWS2_32 */--/* Define to 1 if you have the <limits.h> header file. */-#define HAVE_LIMITS_H 1--/* Define to 1 if you have the <linux/can.h> header file. */-#define HAVE_LINUX_CAN_H 1--/* Define to 1 if you have a Linux sendfile(2) implementation. */-#define HAVE_LINUX_SENDFILE 1--/* Define to 1 if you have the <linux/tcp.h> header file. */-#define HAVE_LINUX_TCP_H 1--/* Define to 1 if you have the <memory.h> header file. */-#define HAVE_MEMORY_H 1--/* Define to 1 if you have the <netdb.h> header file. */-#define HAVE_NETDB_H 1--/* Define to 1 if you have the <netinet/in.h> header file. */-#define HAVE_NETINET_IN_H 1--/* Define to 1 if you have the <netinet/tcp.h> header file. */-#define HAVE_NETINET_TCP_H 1--/* Define to 1 if you have the <net/if.h> header file. */-#define HAVE_NET_IF_H 1--/* Define to 1 if you have the `readlink' function. */-#define HAVE_READLINK 1--/* Define to 1 if you have the <stdint.h> header file. */-#define HAVE_STDINT_H 1--/* Define to 1 if you have the <stdlib.h> header file. */-#define HAVE_STDLIB_H 1--/* Define to 1 if you have the <strings.h> header file. */-#define HAVE_STRINGS_H 1--/* Define to 1 if you have the <string.h> header file. */-#define HAVE_STRING_H 1--/* Define to 1 if `msg_accrights' is a member of `struct msghdr'. */-/* #undef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */--/* Define to 1 if `msg_control' is a member of `struct msghdr'. */-#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1--/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */-/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */--/* Define to 1 if you have both SO_PEERCRED and struct ucred. */-#define HAVE_STRUCT_UCRED 1--/* Define to 1 if you have the `symlink' function. */-#define HAVE_SYMLINK 1--/* Define to 1 if you have the <sys/socket.h> header file. */-#define HAVE_SYS_SOCKET_H 1--/* Define to 1 if you have the <sys/stat.h> header file. */-#define HAVE_SYS_STAT_H 1--/* Define to 1 if you have the <sys/types.h> header file. */-#define HAVE_SYS_TYPES_H 1--/* Define to 1 if you have the <sys/uio.h> header file. */-#define HAVE_SYS_UIO_H 1--/* Define to 1 if you have the <sys/un.h> header file. */-#define HAVE_SYS_UN_H 1--/* Define to 1 if you have the <unistd.h> header file. */-#define HAVE_UNISTD_H 1--/* Define to 1 if you have the <winsock2.h> header file. */-/* #undef HAVE_WINSOCK2_H */--/* Define to 1 if you have the <ws2tcpip.h> header file. */-/* #undef HAVE_WS2TCPIP_H */--/* Define to 1 if the `getaddrinfo' function needs WINVER set. */-/* #undef NEED_WINVER_XP */--/* Define to the address where bug reports for this package should be sent. */-#define PACKAGE_BUGREPORT "libraries@haskell.org"--/* Define to the full name of this package. */-#define PACKAGE_NAME "Haskell network package"--/* Define to the full name and version of this package. */-#define PACKAGE_STRING "Haskell network package 2.6.3.1"--/* Define to the one symbol short name of this package. */-#define PACKAGE_TARNAME "network"--/* Define to the home page for this package. */-#define PACKAGE_URL ""--/* Define to the version of this package. */-#define PACKAGE_VERSION "2.6.3.1"--/* Define to 1 if you have the ANSI C header files. */-#define STDC_HEADERS 1--/* Define to empty if `const' does not conform to ANSI C. */-/* #undef const */
network.buildinfo.in view
@@ -4,3 +4,4 @@ cc-options: -DCALLCONV=@CALLCONV@ @EXTRA_CPPFLAGS@ c-sources: @EXTRA_SRCS@ extra-libraries: @EXTRA_LIBS@+install-includes: HsNetworkConfig.h
network.cabal view
@@ -1,5 +1,5 @@ name: network-version: 2.6.3.3+version: 2.6.3.4 license: BSD3 license-file: LICENSE maintainer: Kazu Yamamoto, Evan Borden@@ -12,19 +12,8 @@ you can automatically get it from the right package by adding this to your .cabal file: .- > flag network-uri- > description: Get Network.URI from the network-uri package- > default: True- > > library- > -- ...- > if flag(network-uri)- > build-depends: network-uri >= 2.6, network >= 2.6- > else- > build-depends: network-uri < 2.6, network < 2.6- .- That is, get the module from either network < 2.6 or from- network-uri >= 2.6.+ > build-depends: network-uri-flag category: Network build-type: Configure cabal-version: >=1.8@@ -41,7 +30,12 @@ cbits/winSockErr.c homepage: https://github.com/haskell/network bug-reports: https://github.com/haskell/network/issues-tested-with: GHC == 7.8.4, GHC == 7.10.1, GHC == 7.10.2, GHC == 8.0.1, GHC == 8.0.2+tested-with: GHC == 7.4.2+ , GHC == 7.6.3+ , GHC == 7.8.4+ , GHC == 7.10.3+ , GHC == 8.0.2+ , GHC == 8.2.2 library exposed-modules:@@ -65,7 +59,7 @@ Network.Socket.ByteString.Lazy.Windows build-depends:- base >= 3 && < 5,+ base >= 4.6 && < 5, bytestring < 0.11 if !os(windows)@@ -76,7 +70,7 @@ CPP, DeriveDataTypeable, ForeignFunctionInterface, TypeSynonymInstances include-dirs: include includes: HsNet.h- install-includes: HsNet.h HsNetworkConfig.h+ install-includes: HsNet.h c-sources: cbits/HsNet.c ghc-options: -Wall -fwarn-tabs @@ -88,6 +82,7 @@ build-depends: base < 5, bytestring,+ directory, HUnit, network, test-framework,
+ tests/BadFileDescriptor.hs view
@@ -0,0 +1,51 @@+-- Test code for "threadWait: invalid argument (Bad file descriptor)"+-- See https://ghc.haskell.org/trac/ghc/ticket/14621+-- See https://github.com/haskell/network/issues/287+--+-- % runghc BadFileDescriptor.hs+-- BadFileDescriptor.hs: threadWait: invalid argument (Bad file descriptor)+module Main where++import Control.Concurrent (forkIO)+import Control.Monad (void, forever)+import Network.Socket hiding (recv)+import Network.Socket.ByteString (recv, sendAll)++main :: IO ()+main = do+ let localhost = "localhost"+ listenPort = "9876"+ connectPort = "6789"+ proxy localhost listenPort connectPort++proxy :: HostName -> ServiceName -> ServiceName -> IO ()+proxy localhost listenPort connectPort = do+ fromClient <- serverSocket localhost listenPort+ toServer <- clientSocket localhost connectPort+ void $ forkIO $ relay toServer fromClient+ relay fromClient toServer++relay :: Socket -> Socket -> IO ()+relay s1 s2 = forever $ do+ payload <- recv s1 4096+ sendAll s2 payload++serverSocket :: HostName -> ServiceName -> IO Socket+serverSocket host port = do+ let hints = defaultHints {+ addrFlags = [AI_PASSIVE]+ , addrSocketType = Stream+ }+ addr:_ <- getAddrInfo (Just hints) (Just host) (Just port)+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+ bind sock (addrAddress addr)+ listen sock 1+ fst <$> accept sock++clientSocket :: HostName -> ServiceName -> IO Socket+clientSocket host port = do+ let hints = defaultHints { addrSocketType = Stream }+ addr:_ <- getAddrInfo (Just hints) (Just host) (Just port)+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)+ connect sock (addrAddress addr)+ return sock
tests/Regression.hs view
@@ -1,4 +1,5 @@ -- | Tests for things that didn't work in the past.+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} -- for recv and send module Main where import Network.Socket
tests/Simple.hs view
@@ -1,5 +1,10 @@ {-# LANGUAGE CPP, ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} -- for recv +#if !defined(mingw32_HOST_OS)+# define DOMAIN_SOCKET_SUPPORT 1+#endif+ module Main where import Control.Concurrent (ThreadId, forkIO, myThreadId)@@ -14,6 +19,7 @@ import Network.Socket hiding (recv, recvFrom, send, sendTo) import qualified Network.Socket (recv) import Network.Socket.ByteString+import System.Directory --- To tests for AF_CAN on Linux, you need to bring up a virtual (or real can --- interface.). Run as root:@@ -291,6 +297,17 @@ addr @=? (hostAddress6ToTuple . tupleToHostAddress6) addr #endif +#if defined(DOMAIN_SOCKET_SUPPORT)+testUnix :: Assertion+testUnix = do+ let client sock = send sock testMsg+ server (sock, addr) = do+ msg <- recv sock 1024+ testMsg @=? msg+ SockAddrUnix "" @=? addr+ unixTest client server+#endif+ ------------------------------------------------------------------------ -- Other @@ -312,6 +329,9 @@ , testCase "testRecvFrom" testRecvFrom , testCase "testOverFlowRecvFrom" testOverFlowRecvFrom , testCase "testUserTimeout" testUserTimeout+#if defined(DOMAIN_SOCKET_SUPPORT)+ , testCase "testUnix" testUnix+#endif -- , testCase "testGetPeerCred" testGetPeerCred -- , testCase "testGetPeerEid" testGetPeerEid , testCase "testStringEol" testStringEol@@ -399,6 +419,43 @@ serverPort <- socketPort sock putMVar portVar serverPort return sock++#if defined(DOMAIN_SOCKET_SUPPORT)+unixAddr :: String+unixAddr = "/tmp/network-test"++-- | 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+#endif -- | Run a client/server pair and synchronize them so that the server -- is started before the client and the specified server action is