2018-03-07 19:15:23 +00:00
|
|
|
{- git-annex command
|
|
|
|
-
|
2024-06-10 22:01:36 +00:00
|
|
|
- Copyright 2018-2024 Joey Hess <id@joeyh.name>
|
2018-03-07 19:15:23 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2018-03-07 19:15:23 +00:00
|
|
|
-}
|
|
|
|
|
|
|
|
module Command.P2PStdIO where
|
|
|
|
|
|
|
|
import Command
|
|
|
|
import P2P.IO
|
|
|
|
import P2P.Annex
|
2024-06-10 22:01:36 +00:00
|
|
|
import P2P.Proxy
|
2018-03-07 19:15:23 +00:00
|
|
|
import qualified P2P.Protocol as P2P
|
|
|
|
import qualified Annex
|
|
|
|
import Annex.UUID
|
|
|
|
import qualified CmdLine.GitAnnexShell.Checks as Checks
|
2024-06-12 14:10:11 +00:00
|
|
|
import Remote.Helper.Ssh (openP2PShellConnection', closeP2PShellConnection)
|
2024-06-12 15:37:14 +00:00
|
|
|
import Logs.Location
|
2024-06-17 19:00:11 +00:00
|
|
|
import Logs.Cluster
|
2024-06-12 15:37:14 +00:00
|
|
|
import qualified Remote
|
2018-03-07 19:15:23 +00:00
|
|
|
|
2018-09-25 20:49:59 +00:00
|
|
|
import System.IO.Error
|
|
|
|
|
2018-03-07 19:15:23 +00:00
|
|
|
cmd :: Command
|
|
|
|
cmd = noMessages $ command "p2pstdio" SectionPlumbing
|
|
|
|
"communicate in P2P protocol over stdio"
|
2018-03-08 20:21:16 +00:00
|
|
|
paramUUID (withParams seek)
|
2018-03-07 19:15:23 +00:00
|
|
|
|
|
|
|
seek :: CmdParams -> CommandSeek
|
2018-03-08 20:21:16 +00:00
|
|
|
seek [u] = commandAction $ start $ toUUID u
|
|
|
|
seek _ = giveup "missing UUID parameter"
|
2018-03-07 19:15:23 +00:00
|
|
|
|
2018-03-08 20:21:16 +00:00
|
|
|
start :: UUID -> CommandStart
|
finish CommandStart transition
The hoped for optimisation of CommandStart with -J did not materialize.
In fact, not runnign CommandStart in parallel is slower than -J3.
So, CommandStart are still run in parallel.
(The actual bad performance I've been seeing with -J in my big repo
has to do with building the remoteList.)
But, this is still progress toward making -J faster, because it gets rid
of the onlyActionOn roadblock in the way of making CommandCleanup jobs
run separate from CommandPerform jobs.
Added OnlyActionOn constructor for ActionItem which fixes the
onlyActionOn breakage in the last commit.
Made CustomOutput include an ActionItem, so even things using it can
specify OnlyActionOn.
In Command.Move and Command.Sync, there were CommandStarts that used
includeCommandAction, so output messages, which is no longer allowed.
Fixed by using startingCustomOutput, but that's still not quite right,
since it prevents message display for the includeCommandAction run
inside it too.
2019-06-12 13:23:26 +00:00
|
|
|
start theiruuid = startingCustomOutput (ActionItemOther Nothing) $ do
|
2018-05-25 17:17:56 +00:00
|
|
|
servermode <- liftIO $ do
|
|
|
|
ro <- Checks.checkEnvSet Checks.readOnlyEnv
|
|
|
|
ao <- Checks.checkEnvSet Checks.appendOnlyEnv
|
|
|
|
return $ case (ro, ao) of
|
|
|
|
(True, _) -> P2P.ServeReadOnly
|
|
|
|
(False, True) -> P2P.ServeAppendOnly
|
|
|
|
(False, False) -> P2P.ServeReadWrite
|
2024-06-10 22:01:36 +00:00
|
|
|
Annex.getState Annex.proxyremote >>= \case
|
2024-06-17 19:00:11 +00:00
|
|
|
Nothing ->
|
|
|
|
performLocal theiruuid servermode
|
|
|
|
Just (Right r) ->
|
|
|
|
performProxy theiruuid servermode r
|
|
|
|
Just (Left clusteruuid) ->
|
|
|
|
performProxyCluster theiruuid clusteruuid servermode
|
2024-06-10 22:01:36 +00:00
|
|
|
|
|
|
|
performLocal :: UUID -> P2P.ServerMode -> CommandPerform
|
|
|
|
performLocal theiruuid servermode = do
|
2018-03-07 19:15:23 +00:00
|
|
|
myuuid <- getUUID
|
git-annex-shell: block relay requests
connRepo is only used when relaying git upload-pack and receive-pack.
That's only supposed to be used when git-annex-remotedaemon is serving
git-remote-tor-annex connections over tor. But, it was always set, and
so could be used in other places possibly.
Fixed by making connRepo optional in the P2P protocol interface.
In Command.EnableTor, it's not needed, because it only speaks the
protocol in order to check that it's able to connect back to itself via
the hidden service. So changed that to pass Nothing rather than the git
repo.
In Remote.Helper.Ssh, it's connecting to git-annex-shell p2pstdio,
so is making the requests, so will never need connRepo.
In git-annex-shell p2pstdio, it was accepting git upload-pack and
receive-pack requests over the P2P protocol, even though nothing sent
them. This is arguably a security hole, particularly if the user has
set environment variables like GIT_ANNEX_SHELL_LIMITED to prevent
git push/pull via git-annex-shell.
2024-06-10 17:53:28 +00:00
|
|
|
let conn = stdioP2PConnection Nothing
|
2018-03-08 18:02:18 +00:00
|
|
|
let server = do
|
|
|
|
P2P.net $ P2P.sendMessage (P2P.AUTH_SUCCESS myuuid)
|
|
|
|
P2P.serveAuthed servermode myuuid
|
2018-03-12 17:43:19 +00:00
|
|
|
runst <- liftIO $ mkRunState $ Serving theiruuid Nothing
|
2024-06-17 19:00:11 +00:00
|
|
|
p2pErrHandler (const p2pDone) (runFullProto runst conn server)
|
2024-06-10 22:01:36 +00:00
|
|
|
|
|
|
|
performProxy :: UUID -> P2P.ServerMode -> Remote -> CommandPerform
|
|
|
|
performProxy clientuuid servermode remote = do
|
2024-06-17 19:00:11 +00:00
|
|
|
clientside <- proxyClientSide clientuuid
|
|
|
|
getClientProtocolVersion (Remote.uuid remote) clientside
|
2024-06-11 14:20:11 +00:00
|
|
|
(withclientversion clientside)
|
2024-06-17 19:00:11 +00:00
|
|
|
p2pErrHandler
|
2024-06-10 22:01:36 +00:00
|
|
|
where
|
2024-06-17 18:14:08 +00:00
|
|
|
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
2024-06-17 19:00:11 +00:00
|
|
|
remoteside <- proxySshRemoteSide clientmaxversion remote
|
|
|
|
proxy p2pDone proxymethods servermode clientside remoteside
|
|
|
|
othermsg p2pErrHandler
|
|
|
|
withclientversion _ Nothing = p2pDone
|
2024-06-11 14:20:11 +00:00
|
|
|
|
2024-06-12 15:37:14 +00:00
|
|
|
proxymethods = ProxyMethods
|
|
|
|
{ removedContent = \u k -> logChange k u InfoMissing
|
|
|
|
, addedContent = \u k -> logChange k u InfoPresent
|
|
|
|
}
|
|
|
|
|
2024-06-17 19:00:11 +00:00
|
|
|
performProxyCluster :: UUID -> ClusterUUID -> P2P.ServerMode -> CommandPerform
|
|
|
|
performProxyCluster clientuuid clusteruuid servermode = do
|
|
|
|
clientside <- proxyClientSide clientuuid
|
|
|
|
getClientProtocolVersion (fromClusterUUID clusteruuid) clientside
|
|
|
|
(withclientversion clientside)
|
|
|
|
p2pErrHandler
|
|
|
|
where
|
|
|
|
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
|
|
|
giveup "TODO"
|
|
|
|
withclientversion _ Nothing = p2pDone
|
|
|
|
|
|
|
|
proxyClientSide :: UUID -> Annex ClientSide
|
|
|
|
proxyClientSide clientuuid = do
|
|
|
|
clientrunst <- liftIO (mkRunState $ Serving clientuuid Nothing)
|
|
|
|
return $ ClientSide clientrunst (stdioP2PConnection Nothing)
|
2024-06-10 22:01:36 +00:00
|
|
|
|
2024-06-17 19:00:11 +00:00
|
|
|
-- FIXME: Support special remotes.
|
|
|
|
proxySshRemoteSide :: P2P.ProtocolVersion -> Remote -> Annex RemoteSide
|
|
|
|
proxySshRemoteSide clientmaxversion remote = mkRemoteSide (Remote.uuid remote) $
|
|
|
|
openP2PShellConnection' remote clientmaxversion >>= \case
|
|
|
|
Just conn@(P2P.IO.OpenConnection (remoterunst, remoteconn, _)) ->
|
|
|
|
return $ Just
|
|
|
|
( remoterunst
|
|
|
|
, remoteconn
|
|
|
|
, void $ liftIO $ closeP2PShellConnection conn
|
|
|
|
)
|
|
|
|
_ -> return Nothing
|
|
|
|
|
|
|
|
p2pErrHandler :: (a -> CommandPerform) -> Annex (Either ProtoFailure a) -> CommandPerform
|
|
|
|
p2pErrHandler cont a = a >>= \case
|
|
|
|
-- Avoid displaying an error when the client hung up on us.
|
|
|
|
Left (ProtoFailureIOError e) | isEOFError e -> p2pDone
|
|
|
|
Left e -> giveup (describeProtoFailure e)
|
|
|
|
Right v -> cont v
|
|
|
|
|
|
|
|
p2pDone :: CommandPerform
|
|
|
|
p2pDone = next $ return True
|