This commit is contained in:
Joey Hess 2016-12-24 12:12:58 -04:00
parent fd0b9aaa57
commit f3a4b9191c
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
2 changed files with 35 additions and 25 deletions

View file

@ -12,35 +12,33 @@ module P2P.IO
, P2PConnection(..) , P2PConnection(..)
, connectPeer , connectPeer
, closeConnection , closeConnection
, serveUnixSocket
, setupHandle , setupHandle
, runNetProto , runNetProto
, runNet , runNet
) where ) where
import Common
import P2P.Protocol import P2P.Protocol
import P2P.Address import P2P.Address
import Utility.Process
import Git import Git
import Git.Command import Git.Command
import Utility.AuthToken import Utility.AuthToken
import Utility.SafeCommand
import Utility.SimpleProtocol import Utility.SimpleProtocol
import Utility.Exception
import Utility.Metered import Utility.Metered
import Utility.Tor import Utility.Tor
import Utility.FileSystemEncoding import Utility.FileMode
import Control.Monad
import Control.Monad.Free import Control.Monad.Free
import Control.Monad.IO.Class import Control.Monad.IO.Class
import System.Exit (ExitCode(..)) import System.Exit (ExitCode(..))
import Network.Socket import Network.Socket
import System.IO
import Control.Concurrent import Control.Concurrent
import Control.Concurrent.Async import Control.Concurrent.Async
import qualified Data.ByteString as B import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy as L
import System.Log.Logger (debugM) import System.Log.Logger (debugM)
import qualified Network.Socket as S
-- Type of interpreters of the Proto free monad. -- Type of interpreters of the Proto free monad.
type RunProto m = forall a. (MonadIO m, MonadMask m) => Proto a -> m (Either String a) type RunProto m = forall a. (MonadIO m, MonadMask m) => Proto a -> m (Either String a)
@ -68,6 +66,34 @@ closeConnection conn = do
hClose (connIhdl conn) hClose (connIhdl conn)
hClose (connOhdl conn) hClose (connOhdl conn)
-- Serves the protocol on a unix socket.
--
-- The callback is run to serve a connection, and is responsible for
-- closing the Handle when done.
--
-- Note that while the callback is running, other connections won't be
-- processes, so longterm work should be run in a separate thread by
-- the callback.
serveUnixSocket :: FilePath -> (Handle -> IO ()) -> IO ()
serveUnixSocket unixsocket serveconn = do
nukeFile unixsocket
soc <- S.socket S.AF_UNIX S.Stream S.defaultProtocol
S.bind soc (S.SockAddrUnix unixsocket)
-- Allow everyone to read and write to the socket,
-- so a daemon like tor, that is probably running as a different
-- de sock $ addModes
-- user, can access it.
--
-- Connections have to authenticate to do anything,
-- so it's fine that other local users can connect to the
-- socket.
modifyFileMode unixsocket $ addModes
[groupReadMode, groupWriteMode, otherReadMode, otherWriteMode]
S.listen soc 2
forever $ do
(conn, _) <- S.accept soc
setupHandle conn >>= serveconn
setupHandle :: Socket -> IO Handle setupHandle :: Socket -> IO Handle
setupHandle s = do setupHandle s = do
h <- socketToHandle s ReadWriteMode h <- socketToHandle s ReadWriteMode

View file

@ -14,7 +14,6 @@ import Annex.ChangedRefs
import RemoteDaemon.Types import RemoteDaemon.Types
import RemoteDaemon.Common import RemoteDaemon.Common
import Utility.Tor import Utility.Tor
import Utility.FileMode
import Utility.AuthToken import Utility.AuthToken
import P2P.Protocol as P2P import P2P.Protocol as P2P
import P2P.IO import P2P.IO
@ -33,7 +32,6 @@ import System.Log.Logger (debugM)
import Control.Concurrent.STM import Control.Concurrent.STM
import Control.Concurrent.STM.TBMQueue import Control.Concurrent.STM.TBMQueue
import Control.Concurrent.Async import Control.Concurrent.Async
import qualified Network.Socket as S
-- Run tor hidden service. -- Run tor hidden service.
server :: TransportHandle -> IO () server :: TransportHandle -> IO ()
@ -48,30 +46,16 @@ server th@(TransportHandle (LocalRepo r) _) = do
replicateM_ maxConnections $ replicateM_ maxConnections $
forkIO $ forever $ serveClient th u r q forkIO $ forever $ serveClient th u r q
nukeFile sock
soc <- S.socket S.AF_UNIX S.Stream S.defaultProtocol
S.bind soc (S.SockAddrUnix sock)
-- Allow everyone to read and write to the socket; tor
-- is probably running as a different user.
-- Connections have to authenticate to do anything,
-- so it's fine that other local users can connect to the
-- socket.
modifyFileMode sock $ addModes
[groupReadMode, groupWriteMode, otherReadMode, otherWriteMode]
S.listen soc 2
debugM "remotedaemon" "Tor hidden service running" debugM "remotedaemon" "Tor hidden service running"
forever $ do serveUnixSocket sock $ \conn -> do
(conn, _) <- S.accept soc
h <- setupHandle conn
ok <- atomically $ ifM (isFullTBMQueue q) ok <- atomically $ ifM (isFullTBMQueue q)
( return False ( return False
, do , do
writeTBMQueue q h writeTBMQueue q conn
return True return True
) )
unless ok $ do unless ok $ do
hClose h hClose conn
warningIO "dropped Tor connection, too busy" warningIO "dropped Tor connection, too busy"
go _ Nothing = debugM "remotedaemon" "Tor hidden service not enabled" go _ Nothing = debugM "remotedaemon" "Tor hidden service not enabled"