Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making getAddrInfo polymorphic #587

Merged
merged 12 commits into from
Sep 11, 2024
7 changes: 5 additions & 2 deletions Network/Socket.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
-- > import qualified Control.Exception as E
-- > import Control.Monad (unless, forever, void)
-- > import qualified Data.ByteString as S
-- > import qualified Data.List.NonEmpty as NE
-- > import Network.Socket
-- > import Network.Socket.ByteString (recv, sendAll)
-- >
Expand All @@ -56,7 +57,7 @@
-- > addrFlags = [AI_PASSIVE]
-- > , addrSocketType = Stream
-- > }
-- > head <$> getAddrInfo (Just hints) mhost (Just port)
-- > NE.head <$> getAddrInfoNE (Just hints) mhost (Just port)
-- > open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
-- > setSocketOption sock ReuseAddr 1
-- > withFdSocket sock setCloseOnExecIfNeeded
Expand All @@ -77,6 +78,7 @@
-- >
-- > import qualified Control.Exception as E
-- > import qualified Data.ByteString.Char8 as C
-- > import qualified Data.List.NonEmpty as NE
-- > import Network.Socket
-- > import Network.Socket.ByteString (recv, sendAll)
-- >
Expand All @@ -95,7 +97,7 @@
-- > where
-- > resolve = do
-- > let hints = defaultHints { addrSocketType = Stream }
-- > head <$> getAddrInfo (Just hints) (Just host) (Just port)
-- > NE.head <$> getAddrInfoNE (Just hints) (Just host) (Just port)
-- > open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
-- > connect sock $ addrAddress addr
-- > return sock
Expand All @@ -111,6 +113,7 @@ module Network.Socket (

-- * Address information
getAddrInfo,
getAddrInfoNE,

-- ** Types
HostName,
Expand Down
10 changes: 10 additions & 0 deletions Network/Socket/Info.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

module Network.Socket.Info where

import qualified Data.List.NonEmpty as NE
import Foreign.Marshal.Alloc (alloca, allocaBytes)
import Foreign.Marshal.Utils (maybeWith, with)
import GHC.IO.Exception (IOErrorType(NoSuchThing))
Expand Down Expand Up @@ -290,6 +291,15 @@ getAddrInfo hints node service = alloc getaddrinfo
filteredHints = hints
#endif

getAddrInfoNE
:: Maybe AddrInfo
-> Maybe HostName
-> Maybe ServiceName
-> IO (NE.NonEmpty AddrInfo)
getAddrInfoNE hints node service =
-- getAddrInfo never returns an empty list.
NE.fromList <$> getAddrInfo hints node service
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since getAddrInfoList also does a non-empty check and throws an IO error if the list is empty, you could make getAddrInfoNE the "real" function and implement getAddrInfoList by fmapping toList over the result of getAddrInfoNE?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


followAddrInfo :: Ptr AddrInfo -> IO [AddrInfo]
followAddrInfo ptr_ai
| ptr_ai == nullPtr = return []
Expand Down
3 changes: 2 additions & 1 deletion examples/EchoClient.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Main (main) where

import qualified Control.Exception as E
import qualified Data.ByteString.Char8 as C
import qualified Data.List.NonEmpty as NE
import Network.Socket
import Network.Socket.ByteString (recv, sendAll)

Expand All @@ -23,7 +24,7 @@ runTCPClient host port client = withSocketsDo $ do
where
resolve = do
let hints = defaultHints{addrSocketType = Stream}
head <$> getAddrInfo (Just hints) (Just host) (Just port)
NE.head <$> getAddrInfoNE (Just hints) (Just host) (Just port)
open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
connect sock $ addrAddress addr
return sock
3 changes: 2 additions & 1 deletion examples/EchoServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Control.Concurrent (forkFinally)
import qualified Control.Exception as E
import Control.Monad (forever, unless, void)
import qualified Data.ByteString as S
import qualified Data.List.NonEmpty as NE
import Network.Socket
import Network.Socket.ByteString (recv, sendAll)

Expand All @@ -29,7 +30,7 @@ runTCPServer mhost port server = withSocketsDo $ do
{ addrFlags = [AI_PASSIVE]
, addrSocketType = Stream
}
head <$> getAddrInfo (Just hints) mhost (Just port)
NE.head <$> getAddrInfoNE (Just hints) mhost (Just port)
open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
setSocketOption sock ReuseAddr 1
withFdSocket sock setCloseOnExecIfNeeded
Expand Down
5 changes: 3 additions & 2 deletions tests/Network/Test/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@
import Control.Monad
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as L
import qualified Data.List.NonEmpty as NE
import Network.Socket
import System.Directory
import System.Timeout (timeout)
import Test.Hspec

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 8.4)

The import of ‘Test.Hspec’ is redundant

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 8.4)

The import of ‘Test.Hspec’ is redundant

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 9.4)

The import of ‘Test.Hspec’ is redundant

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 9.4)

The import of ‘Test.Hspec’ is redundant

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 9.6)

The import of ‘Test.Hspec’ is redundant

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 9.6)

The import of ‘Test.Hspec’ is redundant

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 9.8)

The import of ‘Test.Hspec’ is redundant

Check warning on line 42 in tests/Network/Test/Common.hs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 9.8)

The import of ‘Test.Hspec’ is redundant

serverAddr :: String
serverAddr = "127.0.0.1"
Expand Down Expand Up @@ -244,7 +245,7 @@

resolveClient :: SocketType -> HostName -> PortNumber -> IO AddrInfo
resolveClient socketType host port =
head <$> getAddrInfo (Just hints) (Just host) (Just $ show port)
NE.head <$> getAddrInfoNE (Just hints) (Just host) (Just $ show port)
where
hints = defaultHints {
addrSocketType = socketType
Expand All @@ -253,7 +254,7 @@

resolveServer :: SocketType -> HostName -> IO AddrInfo
resolveServer socketType host =
head <$> getAddrInfo (Just hints) (Just host) Nothing
NE.head <$> getAddrInfoNE (Just hints) (Just host) Nothing
where
hints = defaultHints {
addrSocketType = socketType
Expand Down
Loading