
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.
77 lines
2 KiB
Haskell
77 lines
2 KiB
Haskell
{- git-remote-daemon, tor hidden service server and transport
|
|
-
|
|
- Copyright 2016-2025 Joey Hess <id@joeyh.name>
|
|
-
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
|
-}
|
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
module RemoteDaemon.Transport.Tor (server, transport, torSocketFile) where
|
|
|
|
import Annex.Common
|
|
import RemoteDaemon.Types
|
|
import RemoteDaemon.Common
|
|
import Utility.Tor
|
|
import P2P.IO
|
|
import P2P.Auth
|
|
import P2P.Address
|
|
import Annex.UUID
|
|
import qualified RemoteDaemon.Transport.P2PGeneric as P2PGeneric
|
|
|
|
import Control.Concurrent.STM
|
|
import Control.Concurrent.Async
|
|
#ifndef mingw32_HOST_OS
|
|
import System.Posix.User
|
|
#endif
|
|
|
|
-- Run tor hidden service.
|
|
server :: Server
|
|
server ichan th@(TransportHandle (LocalRepo r) _ _) = go
|
|
where
|
|
go = checkstartservice >>= handlecontrol
|
|
|
|
checkstartservice = do
|
|
u <- liftAnnex th getUUID
|
|
msock <- liftAnnex th torSocketFile
|
|
case msock of
|
|
Nothing ->
|
|
return False
|
|
Just socketfile -> do
|
|
void $ async $ startservice socketfile u
|
|
return True
|
|
|
|
startservice socketfile u = do
|
|
sock <- listenUnixSocket socketfile
|
|
P2PGeneric.serveConnections
|
|
loadP2PAuthTokensTor
|
|
(P2PNetName "tor")
|
|
th u r sock
|
|
|
|
handlecontrol servicerunning = do
|
|
msg <- atomically $ readTChan ichan
|
|
case msg of
|
|
-- On reload, the configuration may have changed to
|
|
-- enable the tor hidden service. If it was not
|
|
-- enabled before, start it,
|
|
RELOAD | not servicerunning -> go
|
|
-- We can ignore all other messages; no need
|
|
-- to restart the hidden service when the network
|
|
-- changes as tor takes care of all that.
|
|
_ -> handlecontrol servicerunning
|
|
|
|
-- Connect to peer's tor hidden service. P2PGeneric can do this,
|
|
-- since it uses connectPeer which also supports tor.
|
|
transport :: Transport
|
|
transport = P2PGeneric.transport
|
|
|
|
torSocketFile :: Annex (Maybe OsPath)
|
|
torSocketFile = do
|
|
u <- getUUID
|
|
let ident = fromUUID u
|
|
#ifndef mingw32_HOST_OS
|
|
uid <- liftIO getRealUserID
|
|
#else
|
|
let uid = 0
|
|
#endif
|
|
liftIO $ getHiddenServiceSocketFile torAppName uid ident
|