Skip to content

Commit b8a53a6

Browse files
committed
Moved readIPAndPort parser to ouroboros-network
1 parent c45735a commit b8a53a6

5 files changed

Lines changed: 75 additions & 33 deletions

File tree

cardano-diffusion/lib/Cardano/Network/Diffusion.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
module Cardano.Network.Diffusion
1515
( module Cardano.Network.Diffusion.Types
1616
, run
17+
-- * Utils
18+
, Diffusion.readIPAndPort
1719
) where
1820

1921
import Control.DeepSeq (NFData)

cardano-diffusion/ping/Cardano/Network/Ping.hs

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ import System.IO qualified as IO
108108
import System.Random (initStdGen)
109109
import Text.Read (readMaybe)
110110

111+
import Cardano.Network.Diffusion (readIPAndPort)
111112
import Cardano.Network.Diffusion.Configuration (defaultChainSyncIdleTimeout)
112113
import Cardano.Network.NodeToClient qualified as NodeToClient
113114
import Cardano.Network.NodeToClient.Version
@@ -147,7 +148,7 @@ data PingMode =
147148
-- ^ query handshake parameters
148149
deriving (Eq, Show)
149150

150-
type Port = Word
151+
type Port = Socket.PortNumber
151152

152153
-- | There are three stages for resolving addresses.
153154
--
@@ -335,43 +336,13 @@ argParser =
335336
addrParser :: Parser (Address (Unresolved SRVOrFilePathUnresolved))
336337
addrParser =
337338
argument
338-
( uncurry IP <$> readIPv4AndPort
339-
<|> uncurry IP <$> readIPv6AndPort
339+
( uncurry IP <$> readIPAndPort
340340
<|> readDomainNameOrFilePath
341341
)
342342
( help "List of IP/DNS/SRV address and ports or UNIX socket paths, e.g. 127.0.0.1:3001 [::1]:3001 example.org:3001."
343343
<> metavar "ADDRS"
344344
)
345345
where
346-
-- note: `Read` instances for `IP`, `IPv4`, `IPv6` expect no trailing
347-
-- characters after the address, thus we need to find the split position
348-
-- first.
349-
350-
-- parse IPv4 address and port in a form `127.0.0.1:3001`
351-
readIPv4AndPort :: ReadM (IP, Port)
352-
readIPv4AndPort =
353-
eitherReader $ \s -> do
354-
case splitWith ':' s of
355-
Nothing -> Left s
356-
Just (addrStr, portStr) ->
357-
maybe (Left s) Right $
358-
(,) <$> readMaybe addrStr
359-
<*> readMaybe portStr
360-
361-
-- parse IPv6 address and port in a form `[::1]:3001` or a UNIX file path
362-
readIPv6AndPort :: ReadM (IP, Port)
363-
readIPv6AndPort =
364-
eitherReader $ \s ->
365-
case s of
366-
('[':s') ->
367-
case splitWith ']' s' of
368-
Just (addrStr, ':' : portStr) ->
369-
maybe (Left s) Right $
370-
(,) <$> readMaybe addrStr
371-
<*> readMaybe portStr
372-
_ -> Left s
373-
_ -> Left s
374-
375346
readDomainNameOrFilePath :: ReadM (Address (Unresolved SRVOrFilePathUnresolved))
376347
readDomainNameOrFilePath = eitherReader $ Right . mkAddress
377348

@@ -418,7 +389,7 @@ instance Exception AddressResolutionError where
418389
-- | Log messages to stderr.
419390
--
420391
data PingWarning = AddressResolutionError AddressResolutionError
421-
| DNSResolution DNS.Domain [IP] Word
392+
| DNSResolution DNS.Domain [IP] Port
422393
| Error SomeException
423394
| ConnectError SockAddr SomeException
424395

ouroboros-network/lib/Ouroboros/Network/Diffusion.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ module Ouroboros.Network.Diffusion
1717
, mkInterfaces
1818
, socketAddressType
1919
, module Ouroboros.Network.Diffusion.Types
20+
-- * Utils
21+
, readIPAndPort
2022
) where
2123

2224

ouroboros-network/lib/Ouroboros/Network/Diffusion/Utils.hs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,73 @@
99
module Ouroboros.Network.Diffusion.Utils
1010
( withSockets
1111
, withLocalSocket
12+
, readIPAndPort
1213
) where
1314

1415

16+
import Control.Applicative ((<|>))
1517
import Control.Monad.Class.MonadThrow
1618
import Control.Tracer (Tracer, traceWith)
19+
import Data.Bifunctor (first)
20+
import Data.IP (IP (..), IPv4, IPv6)
1721
import Data.List.NonEmpty (NonEmpty (..))
1822
import Data.List.NonEmpty qualified as NonEmpty
1923
import Data.Typeable (Typeable)
24+
import Network.Socket (PortNumber)
25+
import Options.Applicative (ReadM, eitherReader)
26+
import Text.Read (readMaybe)
2027

2128
import Ouroboros.Network.Snocket (FileDescriptor, Snocket)
2229
import Ouroboros.Network.Snocket qualified as Snocket
2330

2431
import Ouroboros.Network.Diffusion.Types
2532

33+
34+
-- | optparse-applictive parser for `IPv4:Port` or `IPv6:Port`.
35+
--
36+
-- note: `Read` instances for `IP`, `IPv4`, `IPv6` expect no trailing characters
37+
-- after the address, thus we need custom parser which finds the split position
38+
-- first.
39+
readIPAndPort :: ReadM (IP, PortNumber)
40+
readIPAndPort = (first IPv4 <$> readIPv4AndPort)
41+
<|> (first IPv6 <$> readIPv6AndPort)
42+
where
43+
readIPv4AndPort :: ReadM (IPv4, PortNumber)
44+
readIPv4AndPort =
45+
eitherReader $ \s -> do
46+
case splitWith ':' s of
47+
Nothing -> Left s
48+
Just (addrStr, portStr) ->
49+
maybe (Left s) Right $
50+
(,) <$> readMaybe addrStr
51+
<*> readMaybe portStr
52+
53+
54+
-- parse IPv6 address and port in a form `[::1]:3001` or a UNIX file path
55+
readIPv6AndPort :: ReadM (IPv6, PortNumber)
56+
readIPv6AndPort =
57+
eitherReader $ \s ->
58+
case s of
59+
('[':s') ->
60+
case splitWith ']' s' of
61+
Just (addrStr, ':' : portStr) ->
62+
maybe (Left s) Right $
63+
(,) <$> readMaybe addrStr
64+
<*> readMaybe portStr
65+
_ -> Left s
66+
_ -> Left s
67+
68+
splitWith :: Char -> String -> Maybe (String, String)
69+
splitWith c = go ""
70+
where
71+
go _ []
72+
= Nothing
73+
go !acc (a:as)
74+
| a == c
75+
= Just (reverse acc, as)
76+
go !acc (a:as)
77+
= go (a:acc) as
78+
2679
--
2780
-- Socket utility functions
2881
--

ouroboros-network/ouroboros-network.cabal

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ flag nightly
3131
manual: False
3232
default: False
3333

34+
flag optparse-applicative-fork
35+
description: Use optparse-applicative-fork
36+
manual: True
37+
default: False
38+
3439
source-repository head
3540
type: git
3641
location: https://github.com/intersectmbo/ouroboros-network
@@ -335,6 +340,15 @@ library
335340
directory,
336341
unix,
337342

343+
-- Until https://github.com/IntersectMBO/cardano-cli/pull/1390 is merged we
344+
-- need to allow for `optparse-applicative-fork`
345+
if flag(optparse-applicative-fork)
346+
build-depends:
347+
optparse-applicative-fork
348+
else
349+
build-depends:
350+
optparse-applicative
351+
338352
library framework
339353
import: ghc-options
340354
visibility: public

0 commit comments

Comments
 (0)