PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/packages/network-2.2.1.7/Network.hs

http://github.com/Lainepress/hp-2010.2.0.0
Haskell | 450 lines | 280 code | 55 blank | 115 comment | 20 complexity | 6d626bf7c9f294381f1b2d39a9d0020d MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause
  1. {-# LANGUAGE CPP #-}
  2. -----------------------------------------------------------------------------
  3. -- |
  4. -- Module : Network
  5. -- Copyright : (c) The University of Glasgow 2001
  6. -- License : BSD-style (see the file libraries/network/LICENSE)
  7. --
  8. -- Maintainer : libraries@haskell.org
  9. -- Stability : provisional
  10. -- Portability : portable
  11. --
  12. -- The "Network" interface is a \"higher-level\" interface to
  13. -- networking facilities, and it is recommended unless you need the
  14. -- lower-level interface in "Network.Socket".
  15. --
  16. -----------------------------------------------------------------------------
  17. #include "HsNetworkConfig.h"
  18. #ifdef HAVE_GETADDRINFO
  19. -- Use IPv6-capable function definitions if the OS supports it.
  20. #define IPV6_SOCKET_SUPPORT 1
  21. #endif
  22. module Network (
  23. -- * Basic data types
  24. Socket,
  25. PortID(..),
  26. HostName,
  27. PortNumber, -- instance (Eq, Enum, Num, Real, Integral)
  28. -- * Initialisation
  29. withSocketsDo, -- :: IO a -> IO a
  30. -- * Server-side connections
  31. listenOn, -- :: PortID -> IO Socket
  32. accept, -- :: Socket -> IO (Handle, HostName, PortNumber)
  33. sClose, -- :: Socket -> IO ()
  34. -- * Client-side connections
  35. connectTo, -- :: HostName -> PortID -> IO Handle
  36. -- * Simple sending and receiving
  37. {-$sendrecv-}
  38. sendTo, -- :: HostName -> PortID -> String -> IO ()
  39. recvFrom, -- :: HostName -> PortID -> IO String
  40. -- * Miscellaneous
  41. socketPort, -- :: Socket -> IO PortID
  42. -- * Networking Issues
  43. -- ** Buffering
  44. {-$buffering-}
  45. -- ** Improving I\/O Performance over sockets
  46. {-$performance-}
  47. -- ** @SIGPIPE@
  48. {-$sigpipe-}
  49. ) where
  50. import Control.Monad (liftM)
  51. import Data.Maybe (fromJust)
  52. import Network.BSD
  53. import Network.Socket hiding ( accept, socketPort, recvFrom, sendTo, PortNumber )
  54. import qualified Network.Socket as Socket ( accept )
  55. import System.IO
  56. import Prelude
  57. import qualified Control.Exception as Exception
  58. -- ---------------------------------------------------------------------------
  59. -- High Level ``Setup'' functions
  60. -- If the @PortID@ specifies a unix family socket and the @Hostname@
  61. -- differs from that returned by @getHostname@ then an error is
  62. -- raised. Alternatively an empty string may be given to @connectTo@
  63. -- signalling that the current hostname applies.
  64. data PortID =
  65. Service String -- Service Name eg "ftp"
  66. | PortNumber PortNumber -- User defined Port Number
  67. #if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
  68. | UnixSocket String -- Unix family socket in file system
  69. #endif
  70. -- | Calling 'connectTo' creates a client side socket which is
  71. -- connected to the given host and port. The Protocol and socket type is
  72. -- derived from the given port identifier. If a port number is given
  73. -- then the result is always an internet family 'Stream' socket.
  74. connectTo :: HostName -- Hostname
  75. -> PortID -- Port Identifier
  76. -> IO Handle -- Connected Socket
  77. #if defined(IPV6_SOCKET_SUPPORT)
  78. -- IPv6 and IPv4.
  79. connectTo hostname (Service serv) = connect' hostname serv
  80. connectTo hostname (PortNumber port) = connect' hostname (show port)
  81. #else
  82. -- IPv4 only.
  83. connectTo hostname (Service serv) = do
  84. proto <- getProtocolNumber "tcp"
  85. bracketOnError
  86. (socket AF_INET Stream proto)
  87. (sClose) -- only done if there's an error
  88. (\sock -> do
  89. port <- getServicePortNumber serv
  90. he <- getHostByName hostname
  91. connect sock (SockAddrInet port (hostAddress he))
  92. socketToHandle sock ReadWriteMode
  93. )
  94. connectTo hostname (PortNumber port) = do
  95. proto <- getProtocolNumber "tcp"
  96. bracketOnError
  97. (socket AF_INET Stream proto)
  98. (sClose) -- only done if there's an error
  99. (\sock -> do
  100. he <- getHostByName hostname
  101. connect sock (SockAddrInet port (hostAddress he))
  102. socketToHandle sock ReadWriteMode
  103. )
  104. #endif
  105. #if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
  106. connectTo _ (UnixSocket path) = do
  107. bracketOnError
  108. (socket AF_UNIX Stream 0)
  109. (sClose)
  110. (\sock -> do
  111. connect sock (SockAddrUnix path)
  112. socketToHandle sock ReadWriteMode
  113. )
  114. #endif
  115. #if defined(IPV6_SOCKET_SUPPORT)
  116. connect' :: HostName -> ServiceName -> IO Handle
  117. connect' host serv = do
  118. proto <- getProtocolNumber "tcp"
  119. let hints = defaultHints { addrFlags = [AI_ADDRCONFIG]
  120. , addrProtocol = proto
  121. , addrSocketType = Stream }
  122. addrs <- getAddrInfo (Just hints) (Just host) (Just serv)
  123. let addr = head addrs
  124. bracketOnError
  125. (socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
  126. (sClose) -- only done if there's an error
  127. (\sock -> do
  128. connect sock (addrAddress addr)
  129. socketToHandle sock ReadWriteMode
  130. )
  131. #endif
  132. -- | Creates the server side socket which has been bound to the
  133. -- specified port.
  134. --
  135. -- NOTE: To avoid the \"Address already in use\"
  136. -- problems popped up several times on the GHC-Users mailing list we
  137. -- set the 'ReuseAddr' socket option on the listening socket. If you
  138. -- don't want this behaviour, please use the lower level
  139. -- 'Network.Socket.listen' instead.
  140. listenOn :: PortID -- ^ Port Identifier
  141. -> IO Socket -- ^ Connected Socket
  142. #if defined(IPV6_SOCKET_SUPPORT)
  143. -- IPv6 and IPv4.
  144. listenOn (Service serv) = listen' serv
  145. listenOn (PortNumber port) = listen' (show port)
  146. #else
  147. -- IPv4 only.
  148. listenOn (Service serv) = do
  149. proto <- getProtocolNumber "tcp"
  150. bracketOnError
  151. (socket AF_INET Stream proto)
  152. (sClose)
  153. (\sock -> do
  154. port <- getServicePortNumber serv
  155. setSocketOption sock ReuseAddr 1
  156. bindSocket sock (SockAddrInet port iNADDR_ANY)
  157. listen sock maxListenQueue
  158. return sock
  159. )
  160. listenOn (PortNumber port) = do
  161. proto <- getProtocolNumber "tcp"
  162. bracketOnError
  163. (socket AF_INET Stream proto)
  164. (sClose)
  165. (\sock -> do
  166. setSocketOption sock ReuseAddr 1
  167. bindSocket sock (SockAddrInet port iNADDR_ANY)
  168. listen sock maxListenQueue
  169. return sock
  170. )
  171. #endif
  172. #if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
  173. listenOn (UnixSocket path) =
  174. bracketOnError
  175. (socket AF_UNIX Stream 0)
  176. (sClose)
  177. (\sock -> do
  178. setSocketOption sock ReuseAddr 1
  179. bindSocket sock (SockAddrUnix path)
  180. listen sock maxListenQueue
  181. return sock
  182. )
  183. #endif
  184. #if defined(IPV6_SOCKET_SUPPORT)
  185. listen' :: ServiceName -> IO Socket
  186. listen' serv = do
  187. proto <- getProtocolNumber "tcp"
  188. let hints = defaultHints { addrFlags = [AI_ADDRCONFIG, AI_PASSIVE]
  189. , addrSocketType = Stream
  190. , addrProtocol = proto }
  191. addrs <- getAddrInfo (Just hints) Nothing (Just serv)
  192. let addr = head addrs
  193. bracketOnError
  194. (socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
  195. (sClose)
  196. (\sock -> do
  197. setSocketOption sock ReuseAddr 1
  198. bindSocket sock (addrAddress addr)
  199. listen sock maxListenQueue
  200. return sock
  201. )
  202. #endif
  203. -- -----------------------------------------------------------------------------
  204. -- accept
  205. -- | Accept a connection on a socket created by 'listenOn'. Normal
  206. -- I\/O operations (see "System.IO") can be used on the 'Handle'
  207. -- returned to communicate with the client.
  208. -- Notice that although you can pass any Socket to Network.accept,
  209. -- only sockets of either AF_UNIX, AF_INET, or AF_INET6 will work
  210. -- (this shouldn't be a problem, though). When using AF_UNIX, HostName
  211. -- will be set to the path of the socket and PortNumber to -1.
  212. --
  213. accept :: Socket -- ^ Listening Socket
  214. -> IO (Handle,
  215. HostName,
  216. PortNumber) -- ^ Triple of: read\/write 'Handle' for
  217. -- communicating with the client,
  218. -- the 'HostName' of the peer socket, and
  219. -- the 'PortNumber' of the remote connection.
  220. accept sock@(MkSocket _ AF_INET _ _ _) = do
  221. ~(sock', (SockAddrInet port haddr)) <- Socket.accept sock
  222. peer <- catchIO
  223. (do
  224. (HostEntry peer _ _ _) <- getHostByAddr AF_INET haddr
  225. return peer
  226. )
  227. (\e -> inet_ntoa haddr)
  228. -- if getHostByName fails, we fall back to the IP address
  229. handle <- socketToHandle sock' ReadWriteMode
  230. return (handle, peer, port)
  231. #if defined(IPV6_SOCKET_SUPPORT)
  232. accept sock@(MkSocket _ AF_INET6 _ _ _) = do
  233. (sock', addr) <- Socket.accept sock
  234. peer <- catchIO ((fromJust . fst) `liftM` getNameInfo [] True False addr) $
  235. \_ -> case addr of
  236. SockAddrInet _ a -> inet_ntoa a
  237. SockAddrInet6 _ _ a _ -> return (show a)
  238. # if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
  239. SockAddrUnix a -> return a
  240. # endif
  241. a -> return (show a)
  242. handle <- socketToHandle sock' ReadWriteMode
  243. let port = case addr of
  244. SockAddrInet p _ -> p
  245. SockAddrInet6 p _ _ _ -> p
  246. _ -> -1
  247. return (handle, peer, port)
  248. #endif
  249. #if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
  250. accept sock@(MkSocket _ AF_UNIX _ _ _) = do
  251. ~(sock', (SockAddrUnix path)) <- Socket.accept sock
  252. handle <- socketToHandle sock' ReadWriteMode
  253. return (handle, path, -1)
  254. #endif
  255. accept sock@(MkSocket _ family _ _ _) =
  256. error $ "Sorry, address family " ++ (show family) ++ " is not supported!"
  257. -- -----------------------------------------------------------------------------
  258. -- sendTo/recvFrom
  259. {-$sendrecv
  260. Send and receive data from\/to the given host and port number. These
  261. should normally only be used where the socket will not be required for
  262. further calls. Also, note that due to the use of 'hGetContents' in 'recvFrom'
  263. the socket will remain open (i.e. not available) even if the function already
  264. returned. Their use is strongly discouraged except for small test-applications
  265. or invocations from the command line.
  266. -}
  267. sendTo :: HostName -- Hostname
  268. -> PortID -- Port Number
  269. -> String -- Message to send
  270. -> IO ()
  271. sendTo h p msg = do
  272. s <- connectTo h p
  273. hPutStr s msg
  274. hClose s
  275. recvFrom :: HostName -- Hostname
  276. -> PortID -- Port Number
  277. -> IO String -- Received Data
  278. #if defined(IPV6_SOCKET_SUPPORT)
  279. recvFrom host port = do
  280. proto <- getProtocolNumber "tcp"
  281. let hints = defaultHints { addrFlags = [AI_ADDRCONFIG]
  282. , addrProtocol = proto
  283. , addrSocketType = Stream }
  284. allowed <- map addrAddress `liftM` getAddrInfo (Just hints) (Just host)
  285. Nothing
  286. s <- listenOn port
  287. let waiting = do
  288. (s', addr) <- Socket.accept s
  289. if not (addr `oneOf` allowed)
  290. then sClose s' >> waiting
  291. else socketToHandle s' ReadMode >>= hGetContents
  292. waiting
  293. where
  294. a@(SockAddrInet _ ha) `oneOf` ((SockAddrInet _ hb):bs)
  295. | ha == hb = True
  296. | otherwise = a `oneOf` bs
  297. a@(SockAddrInet6 _ _ ha _) `oneOf` ((SockAddrInet6 _ _ hb _):bs)
  298. | ha == hb = True
  299. | otherwise = a `oneOf` bs
  300. _ `oneOf` _ = False
  301. #else
  302. recvFrom host port = do
  303. ip <- getHostByName host
  304. let ipHs = hostAddresses ip
  305. s <- listenOn port
  306. let
  307. waiting = do
  308. ~(s', SockAddrInet _ haddr) <- Socket.accept s
  309. he <- getHostByAddr AF_INET haddr
  310. if not (any (`elem` ipHs) (hostAddresses he))
  311. then do
  312. sClose s'
  313. waiting
  314. else do
  315. h <- socketToHandle s' ReadMode
  316. msg <- hGetContents h
  317. return msg
  318. message <- waiting
  319. return message
  320. #endif
  321. -- ---------------------------------------------------------------------------
  322. -- Access function returning the port type/id of socket.
  323. -- | Returns the 'PortID' associated with a given socket.
  324. socketPort :: Socket -> IO PortID
  325. socketPort s = do
  326. sockaddr <- getSocketName s
  327. return (portID sockaddr)
  328. where
  329. portID sa =
  330. case sa of
  331. SockAddrInet port _ -> PortNumber port
  332. #if defined(IPV6_SOCKET_SUPPORT)
  333. SockAddrInet6 port _ _ _ -> PortNumber port
  334. #endif
  335. #if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
  336. SockAddrUnix path -> UnixSocket path
  337. #endif
  338. -- ---------------------------------------------------------------------------
  339. -- Utils
  340. #if __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ < 606
  341. -- Like bracket, but only performs the final action if there was an
  342. -- exception raised by the middle bit.
  343. bracketOnError
  344. :: IO a -- ^ computation to run first (\"acquire resource\")
  345. -> (a -> IO b) -- ^ computation to run last (\"release resource\")
  346. -> (a -> IO c) -- ^ computation to run in-between
  347. -> IO c -- returns the value from the in-between computation
  348. bracketOnError before after thing =
  349. Exception.block (do
  350. a <- before
  351. r <- Exception.catch
  352. (Exception.unblock (thing a))
  353. (\e -> do { after a; Exception.throw e })
  354. return r
  355. )
  356. #else
  357. bracketOnError = Exception.bracketOnError
  358. #endif
  359. -----------------------------------------------------------------------------
  360. -- Extra documentation
  361. {-$buffering
  362. The 'Handle' returned by 'connectTo' and 'accept' is block-buffered by
  363. default. For an interactive application you may want to set the
  364. buffering mode on the 'Handle' to
  365. 'LineBuffering' or 'NoBuffering', like so:
  366. > h <- connectTo host port
  367. > hSetBuffering h LineBuffering
  368. -}
  369. {-$performance
  370. For really fast I\/O, it might be worth looking at the 'hGetBuf' and
  371. 'hPutBuf' family of functions in "System.IO".
  372. -}
  373. {-$sigpipe
  374. On Unix, when writing to a socket and the reading end is
  375. closed by the remote client, the program is normally sent a
  376. @SIGPIPE@ signal by the operating system. The
  377. default behaviour when a @SIGPIPE@ is received is
  378. to terminate the program silently, which can be somewhat confusing
  379. if you haven't encountered this before. The solution is to
  380. specify that @SIGPIPE@ is to be ignored, using
  381. the POSIX library:
  382. > import Posix
  383. > main = do installHandler sigPIPE Ignore Nothing; ...
  384. -}
  385. catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a
  386. #ifdef BASE4
  387. catchIO = Exception.catch
  388. #else
  389. catchIO = Exception.catchJust Exception.ioErrors
  390. #endif