Skip to content

Commit

Permalink
Support network-3
Browse files Browse the repository at this point in the history
  • Loading branch information
phadej committed Jul 2, 2019
1 parent c472e53 commit b4dbd1a
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 7 deletions.
14 changes: 13 additions & 1 deletion HaskellNet.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ Source-Repository head
type: git
location: git://github.com/jtdaugherty/HaskellNet.git

Flag network-bsd
description: Use network-bsd
manual: False
default: True

Library
Hs-Source-Dirs: src
GHC-Options: -Wall -fno-warn-unused-do-bind
Expand All @@ -54,12 +59,13 @@ Library
Network.HaskellNet.Debug

Other-modules:
Network.Compat
Text.Packrat.Pos
Text.Packrat.Parse

Build-Depends:
base >= 4.3 && < 4.13,
network >= 2 && < 3,
network >= 2.6.3.1 && < 3.2,
mtl,
bytestring >=0.10.2,
pretty,
Expand All @@ -69,3 +75,9 @@ Library
old-time,
mime-mail >= 0.4.7 && < 0.6,
text

if flag(network-bsd)
Build-Depends: network-bsd >=2.7 && <2.9,
network >=2.7
else
Build-Depends: network <2.7
53 changes: 53 additions & 0 deletions src/Network/Compat.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module Network.Compat where

import Network.Socket
import Network.BSD (getProtocolNumber)
import System.IO (Handle, IOMode (..))

import qualified Control.Exception as Exception

connectTo :: String -- Hostname
-> PortNumber -- Port Identifier
-> IO Handle -- Connected Socket
connectTo host port = do
proto <- getProtocolNumber "tcp"
let hints = defaultHints { addrFlags = [AI_ADDRCONFIG]
, addrProtocol = proto
, addrSocketType = Stream }
addrs <- getAddrInfo (Just hints) (Just host) (Just serv)
firstSuccessful "connectTo" $ map tryToConnect addrs
where
serv = show port

tryToConnect addr =
Exception.bracketOnError
(socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
close -- only done if there's an error
(\sock -> do
connect sock (addrAddress addr)
socketToHandle sock ReadWriteMode
)

-- Returns the first action from a list which does not throw an exception.
-- If all the actions throw exceptions (and the list of actions is not empty),
-- the last exception is thrown.
-- The operations are run outside of the catchIO cleanup handler because
-- catchIO masks asynchronous exceptions in the cleanup handler.
-- In the case of complete failure, the last exception is actually thrown.
firstSuccessful :: String -> [IO a] -> IO a
firstSuccessful caller = go Nothing
where
-- Attempt the next operation, remember exception on failure
go _ (p:ps) =
do r <- tryIO p
case r of
Right x -> return x
Left e -> go (Just e) ps

-- All operations failed, throw error if one exists
go Nothing [] = ioError $ userError $ caller ++ ": firstSuccessful: empty list"
go (Just e) [] = Exception.throwIO e

-- Version of try implemented in terms of the locally defined catchIO
tryIO :: IO a -> IO (Either Exception.IOException a)
tryIO m = Exception.catch (fmap Right m) (return . Left)
5 changes: 3 additions & 2 deletions src/Network/HaskellNet/IMAP.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ module Network.HaskellNet.IMAP
)
where

import Network
import Network.Socket (PortNumber)
import Network.Compat
import Network.HaskellNet.BSStream
import Network.HaskellNet.IMAP.Connection
import Network.HaskellNet.IMAP.Types
Expand Down Expand Up @@ -116,7 +117,7 @@ data FlagsQuery = ReplaceFlags [Flag]

connectIMAPPort :: String -> PortNumber -> IO IMAPConnection
connectIMAPPort hostname port =
handleToStream <$> connectTo hostname (PortNumber port)
handleToStream <$> connectTo hostname port
>>= connectStream

connectIMAP :: String -> IO IMAPConnection
Expand Down
5 changes: 3 additions & 2 deletions src/Network/HaskellNet/POP3.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ module Network.HaskellNet.POP3
where

import Network.HaskellNet.BSStream
import Network
import Network.Socket
import Network.Compat
import qualified Network.HaskellNet.Auth as A

import Data.ByteString (ByteString)
Expand Down Expand Up @@ -74,7 +75,7 @@ stripEnd = BS.reverse . trimR
-- number
connectPop3Port :: String -> PortNumber -> IO POP3Connection
connectPop3Port hostname port =
handleToStream <$> (connectTo hostname (PortNumber port))
handleToStream <$> (connectTo hostname port)
>>= connectStream

-- | connecting to the pop3 server specified by the hostname. 110 is
Expand Down
5 changes: 3 additions & 2 deletions src/Network/HaskellNet/SMTP.hs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ import Network.HaskellNet.BSStream
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BS
import Network.BSD (getHostName)
import Network
import Network.Socket
import Network.Compat

import Control.Applicative ((<$>))
import Control.Exception
Expand Down Expand Up @@ -140,7 +141,7 @@ connectSMTPPort :: String -- ^ name of the server
-> PortNumber -- ^ port number
-> IO SMTPConnection
connectSMTPPort hostname port =
(handleToStream <$> connectTo hostname (PortNumber port))
(handleToStream <$> connectTo hostname port)
>>= connectStream

-- | connecting SMTP server with the specified name and port 25.
Expand Down

0 comments on commit b4dbd1a

Please sign in to comment.