support P2PAnnex in connectPeer

This is probably enough to support accessing remotes using p2p-annex:: urls.
Not tested yet of course since there is not yet support for serving the
other side of such a connection, or for setting up such a connection.

P2P.Generic has an implementation of the whole interface to the
git-annex-p2p-<netname> commands.
This commit is contained in:
Joey Hess 2025-07-30 13:21:29 -04:00
commit 4fb9b7cb67
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 78 additions and 9 deletions

57
P2P/Generic.hs Normal file
View file

@ -0,0 +1,57 @@
{- 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
genericP2PCommand :: P2PNetName -> String
genericP2PCommand (P2PNetName netname) = "git-annex-p2p-" ++ netname
connectGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> CreateProcess
connectGenericP2P netname (UnderlyingP2PAddress address) =
(proc (genericP2PCommand netname) [address])
{ std_in = CreatePipe
, std_out = CreatePipe
}
socketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> CreateProcess
socketGenericP2P netname (UnderlyingP2PAddress address) =
(proc (genericP2PCommand netname) ["socket", address])
{ std_in = CreatePipe
}
addressGenericP2P :: P2PNetName -> CreateProcess
addressGenericP2P netname =
(proc (genericP2PCommand netname) ["address"])
{ std_in = CreatePipe
}
getSocketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> IO (Maybe (OsPath, ProcessHandle))
getSocketGenericP2P netname address = do
(Just hin, Nothing, Nothing, pid) <- createProcess $
socketGenericP2P netname address
hGetLineUntilExitOrEOF pid hin >>= \case
Just l | not (null l) -> return $ Just (toOsPath l, pid)
_ -> return Nothing
getAddressGenericP2P :: P2PNetName -> IO [P2PAddress]
getAddressGenericP2P netname = do
(Just hin, Nothing, Nothing, pid) <- createProcess $
addressGenericP2P netname
go [] hin pid
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 -> return addrs

View file

@ -1,6 +1,6 @@
{- P2P protocol, IO implementation
-
- Copyright 2016-2024 Joey Hess <id@joeyh.name>
- Copyright 2016-2025 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
@ -20,7 +20,6 @@ module P2P.IO
, connectPeer
, closeConnection
, serveUnixSocket
, setupHandle
, ProtoFailure(..)
, describeProtoFailure
, runNetProto
@ -31,6 +30,7 @@ module P2P.IO
import Common
import P2P.Protocol
import P2P.Address
import P2P.Generic
import Git
import Git.Command
import Utility.AuthToken
@ -138,7 +138,7 @@ stdioP2PConnectionDupped g = do
-- Opens a connection to a peer. Does not authenticate with it.
connectPeer :: Maybe Git.Repo -> P2PAddress -> IO P2PConnection
connectPeer g (TorAnnex onionaddress onionport) = do
h <- setupHandle =<< connectHiddenService onionaddress onionport
h <- setupHandleFromSocket =<< connectHiddenService onionaddress onionport
return $ P2PConnection
{ connRepo = g
, connCheckAuth = const False
@ -147,6 +147,17 @@ connectPeer g (TorAnnex onionaddress onionport) = do
, connProcess = Nothing
, connIdent = ConnIdent Nothing
}
connectPeer g (P2PAnnex netname address) = do
(Just hin, Just hout, Nothing, pid) <- createProcess $
connectGenericP2P netname address
return $ P2PConnection
{ connRepo = g
, connCheckAuth = const False
, connIhdl = P2PHandle hout
, connOhdl = P2PHandle hin
, connProcess = Just pid
, connIdent = ConnIdent Nothing
}
closeConnection :: P2PConnection -> IO ()
closeConnection conn = do
@ -185,10 +196,10 @@ serveUnixSocket unixsocket serveconn = do
S.listen soc 2
forever $ do
(conn, _) <- S.accept soc
setupHandle conn >>= serveconn
setupHandleFromSocket conn >>= serveconn
setupHandle :: Socket -> IO Handle
setupHandle s = do
setupHandleFromSocket :: Socket -> IO Handle
setupHandleFromSocket s = do
h <- socketToHandle s ReadWriteMode
hSetBuffering h LineBuffering
hSetBinaryMode h False

View file

@ -33,9 +33,9 @@ to convert the P2P network's own equivilant into a unix socket file.
To configure `git-annex remotedaemon` to listen on a given P2P network,
the user runs `git-annex p2p --enable <netname>`. That also
runs `git-annex-p2p-<netname>`, this time with the parameter "address".
That should output a single line, the P2P network address that can be used
by peers to connect to the repository. It can first do whatever it needs to
do to set up the P2P network.
That should output one or more lines, the P2P network address (or addresses)
that can be used by peers to connect to the repository. It can first do
whatever it needs to do to set up the P2P network.
The program [[git-remote-p2p-annex]] is included in git-annex as a git
remote helper program. git will use that program to handle `pull` and

View file

@ -923,6 +923,7 @@ Executable git-annex
P2P.Address
P2P.Annex
P2P.Auth
P2P.Generic
P2P.Http.Types
P2P.Http.Client
P2P.Http.Url