git-annex/P2P/Generic.hs
Joey Hess f1781d01d8
remotedaemon support for generic P2P transports
RemoteDaemon.Transport.Tor was refactored into this, and most of the
code is reused between them.

getSocketFile does not yet deal with repositories on crippled
filesystems that don't support sockets. Annex.Ssh detects that and
allows the user to set an environment variable, and something similar
could be done here.

And it does not deal with a situation where there is no path to the
socket file that is not too long. In that situation it would crash out
I suppose. Probably though, remotedaemon is ran from the top of the
repo, and in that case the path is just ".git/annex/p2p/<md5>" so nice
and short.

This seems to mostly work. But I don't yet have a working git-annex-p2p-
command to test it with.

And with my not quite working git-annex-p2p-foo test script, running
remotedaemon results in an ever-growing number of zombie processes
that it's not waiting on.
2025-07-31 14:45:32 -04:00

66 lines
2.1 KiB
Haskell

{- P2P protocol, generic transports.
-
- See doc/design/generic_p2p_transport.mdwn
-
- Copyright 2025 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
module P2P.Generic where
import Common
import P2P.Address
import Annex.ExternalAddonProcess
genericP2PCommand :: P2PNetName -> String
genericP2PCommand (P2PNetName netname) = "git-annex-p2p-" ++ netname
connectGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> IO (Handle, Handle, ProcessHandle)
connectGenericP2P netname (UnderlyingP2PAddress address) =
startExternalAddonProcess
(\p -> p
{ std_in = CreatePipe
, std_out = CreatePipe
})
(genericP2PCommand netname) [Param address]
>>= \case
Right (_, (Just hin, Just hout, Nothing, pid)) ->
return (hin, hout, pid)
Right _ -> giveup "internal"
Left (ProgramNotInstalled msg) -> giveup msg
Left (ProgramFailure msg) -> giveup msg
socketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> OsPath -> IO ProcessHandle
socketGenericP2P netname (UnderlyingP2PAddress address) socketfile = do
startExternalAddonProcess id
(genericP2PCommand netname) [Param address, File (fromOsPath socketfile)]
>>= \case
Right (_, (Nothing, Nothing, Nothing, pid)) ->
return pid
Right _ -> giveup "internal"
Left (ProgramNotInstalled msg) -> giveup msg
Left (ProgramFailure msg) -> giveup msg
getAddressGenericP2P :: P2PNetName -> IO [P2PAddress]
getAddressGenericP2P netname =
startExternalAddonProcess
(\p -> p { std_out = CreatePipe })
(genericP2PCommand netname) [Param "address"]
>>= \case
Right (_, (Nothing, Just hin, Nothing, pid)) ->
go [] hin pid
Right _ -> giveup "internal"
Left (ProgramNotInstalled msg) -> giveup msg
Left (ProgramFailure msg) -> giveup msg
where
go addrs hin pid = hGetLineUntilExitOrEOF pid hin >>= \case
Just l
| not (null l) ->
let addr = P2PAnnex netname (UnderlyingP2PAddress l)
in go (addr:addrs) hin pid
| otherwise -> go addrs hin pid
Nothing -> do
waitForProcess pid >>= \case
ExitSuccess -> return addrs
ExitFailure _ -> giveup $ genericP2PCommand netname ++ " failed"