From 0ef0bfedc65cc67cbe8ad66ab9ae2fb9ae20b7f3 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 29 Jul 2017 03:13:26 -0400 Subject: Refactoring for tox/mainline code-sharing. --- src/Network/Address.hs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src/Network') diff --git a/src/Network/Address.hs b/src/Network/Address.hs index 8715a82d..cc06ac0d 100644 --- a/src/Network/Address.hs +++ b/src/Network/Address.hs @@ -35,6 +35,11 @@ module Network.Address , IPv4 , IPv6 , IP (..) + , un4map + , WantIP (..) + , ipFamily + , is4mapped + , either4or6 -- * PeerId -- $peer-id @@ -1180,3 +1185,35 @@ getBindAddress listenPortString enabled6 = do else SockAddrInet (parsePort listenPortString) iNADDR_ANY where parsePort s = fromMaybe 0 $ readMaybe s return listenAddr + +-- | True if the argument is an IPv4-mapped address with prefix ::FFFF:0:0/96 +-- as defined in RFC 4291. +is4mapped :: IPv6 -> Bool +is4mapped ip + | [0,0,0,0,0,0xffff,_,_] <- fromIPv6 ip + = True + | otherwise = False + +un4map :: IPv6 -> Maybe IPv4 +un4map ip + | [0,0,0,0,0,0xffff,x,y] <- fromIPv6 ip + = Just $ toIPv4 + $ L.map (.&. 0xFF) + [x `shiftR` 8, x, y `shiftR` 8, y ] + | otherwise = Nothing + +ipFamily :: IP -> WantIP +ipFamily ip = case ip of + IPv4 _ -> Want_IP4 + IPv6 a | is4mapped a -> Want_IP4 + | otherwise -> Want_IP6 + +either4or6 :: SockAddr -> Either SockAddr SockAddr +either4or6 a4@(SockAddrInet port addr) = Left a4 +either4or6 a6@(SockAddrInet6 port _ addr _) + | Just ip4 <- (fromSockAddr a6 >>= un4map) = Left (setPort port $ toSockAddr ip4) + | otherwise = Right a6 + +data WantIP = Want_IP4 | Want_IP6 | Want_Both + deriving (Eq, Enum, Ord, Show) + -- cgit v1.2.3