{- P2P protocol addresses
-
- - Copyright 2016 Joey Hess <id@joeyh.name>
+ - Copyright 2016-2025 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
--
-- This is enough information to connect to the peer,
-- but not enough to authenticate with it.
-data P2PAddress = TorAnnex OnionAddress OnionPort
+data P2PAddress
+ = TorAnnex OnionAddress OnionPort
+ | P2PAnnex P2PNetName UnderlyingP2PAddress
+ deriving (Eq, Show)
+
+newtype P2PNetName = P2PNetName String
+ deriving (Eq, Show)
+
+newtype UnderlyingP2PAddress = UnderlyingP2PAddress String
deriving (Eq, Show)
-- | A P2P address, with an AuthToken.
instance FormatP2PAddress P2PAddress where
formatP2PAddress (TorAnnex (OnionAddress onionaddr) onionport) =
torAnnexScheme ++ ":" ++ onionaddr ++ ":" ++ show onionport
+ formatP2PAddress (P2PAnnex (P2PNetName netname) (UnderlyingP2PAddress address)) =
+ p2pAnnexScheme ++ ":" ++ netname ++ ":" ++ address
unformatP2PAddress s
- | (torAnnexScheme ++ ":") `isPrefixOf` s = do
- let s' = dropWhile (== ':') $ dropWhile (/= ':') s
- let (onionaddr, ps) = separate (== ':') s'
- onionport <- readish ps
- return (TorAnnex (OnionAddress onionaddr) onionport)
+ | schemeprefixed torAnnexScheme = do
+ onionport <- readish bs
+ return (TorAnnex (OnionAddress as) onionport)
+ | schemeprefixed p2pAnnexScheme =
+ return (P2PAnnex (P2PNetName as) (UnderlyingP2PAddress bs))
| otherwise = Nothing
+ where
+ schemeprefixed scheme = (scheme ++ ":") `isPrefixOf` s
+ (as, bs) = separate (== ':') $
+ dropWhile (== ':') $ dropWhile (/= ':') s
torAnnexScheme :: String
torAnnexScheme = "tor-annex:"
+p2pAnnexScheme :: String
+p2pAnnexScheme = "p2p-annex:"
+
instance FormatP2PAddress P2PAddressAuth where
formatP2PAddress (P2PAddressAuth addr authtoken) =
formatP2PAddress addr ++ ":" ++ T.unpack (fromAuthToken authtoken)
import Utility.Tor
import Utility.Env
+import Network.URI
+import Data.Char
import qualified Data.Text as T
-- | Load authtokens that are accepted by this repository for tor.
where
v = case addr of
TorAnnex _ _ -> (t, Nothing)
- -- _ -> (t, Just addr)
+ _ -> (t, Just addr)
fmt (tok, Nothing) = T.unpack (fromAuthToken tok)
fmt (tok, Just addr') = T.unpack (fromAuthToken tok)
(T.unpack $ fromAuthToken t)
(addressCredsFile addr)
+-- | Unusual characters in the address are url encoded.
addressCredsFile :: P2PAddress -> OsPath
--- We can omit the port and just use the onion address for the creds file,
--- because any given tor hidden service runs on a single port and has a
--- unique onion address.
-addressCredsFile (TorAnnex (OnionAddress onionaddr) _port) =
- toOsPath onionaddr
+addressCredsFile addr = toOsPath $ escapeURIString isAlphaNum $ case addr of
+ -- We can omit the port and just use the onion address for the
+ -- creds file, because any given tor hidden service runs on a
+ -- single port and has a unique onion address.
+ TorAnnex (OnionAddress onionaddr) _port ->
+ onionaddr
+ P2PAnnex (P2PNetName netname) (UnderlyingP2PAddress address) ->
+ netname ++ ":" ++ address