module TahoeLAFS.Storage.Server (
StorageServerConfig (StorageServerConfig),
app,
main,
) where
import Control.Exception (
Exception,
throw,
)
import Control.Monad.IO.Class (
liftIO,
)
import Data.Maybe (fromMaybe)
import Network.HTTP.Types (
ByteRanges,
)
import Network.Wai (
Application,
)
import Network.Wai.Handler.Warp (
Port,
defaultSettings,
runSettings,
setPort,
)
import Network.Wai.Handler.WarpTLS (
runTLS,
tlsSettings,
)
import Servant (
Handler,
Server,
serve,
(:<|>) (..),
)
import TahoeLAFS.Storage.API (
AllocateBuckets,
AllocationResult (..),
CBORSet (..),
CorruptionDetails,
LeaseSecret (Write),
QueryRange,
ReadTestWriteResult (..),
ReadTestWriteVectors,
ShareData,
ShareNumber,
StorageAPI,
StorageIndex,
Version (..),
api,
)
import TahoeLAFS.Storage.Backend (WriteImmutableError (MissingUploadSecret))
import qualified TahoeLAFS.Storage.Backend as Backend
import TahoeLAFS.Storage.Backend.Filesystem (
FilesystemBackend (FilesystemBackend),
)
version :: Backend.Backend b => b -> Handler Version
version backend =
liftIO (Backend.version backend)
renewLease :: Backend.Backend b => b -> StorageIndex -> Maybe [LeaseSecret] -> Handler ()
renewLease backend storageIndex secrets = liftIO (Backend.renewLease backend storageIndex (fromMaybe [] secrets))
createImmutableStorageIndex :: Backend.Backend b => b -> StorageIndex -> Maybe [LeaseSecret] -> AllocateBuckets -> Handler AllocationResult
createImmutableStorageIndex backend storageIndex secrets params =
liftIO (Backend.createImmutableStorageIndex backend storageIndex secrets params)
writeImmutableShare :: Backend.Backend b => b -> StorageIndex -> ShareNumber -> Maybe [LeaseSecret] -> ShareData -> Maybe ByteRanges -> Handler ()
writeImmutableShare backend storage_index share_number secrets share_data content_ranges =
liftIO (Backend.writeImmutableShare backend storage_index share_number secrets share_data content_ranges)
abortImmutableUpload :: Backend.Backend b => b -> StorageIndex -> ShareNumber -> Maybe [LeaseSecret] -> Handler ()
abortImmutableUpload backend storageIndex shareNum secrets = liftIO (Backend.abortImmutableUpload backend storageIndex shareNum secrets)
adviseCorruptImmutableShare :: Backend.Backend b => b -> StorageIndex -> ShareNumber -> CorruptionDetails -> Handler ()
adviseCorruptImmutableShare backend storage_index share_number details =
liftIO (Backend.adviseCorruptImmutableShare backend storage_index share_number details)
getImmutableShareNumbers :: Backend.Backend b => b -> StorageIndex -> Handler (CBORSet ShareNumber)
getImmutableShareNumbers backend storage_index =
liftIO (Backend.getImmutableShareNumbers backend storage_index)
readImmutableShare :: Backend.Backend b => b -> StorageIndex -> ShareNumber -> QueryRange -> Handler ShareData
readImmutableShare backend storage_index share_number qr =
-- TODO Need to return NO CONTENT if the result is empty.
-- TODO Need to make sure content-range is set in the header otherwise
liftIO (Backend.readImmutableShare backend storage_index share_number qr)
readvAndTestvAndWritev :: Backend.Backend b => b -> StorageIndex -> Maybe [LeaseSecret] -> ReadTestWriteVectors -> Handler ReadTestWriteResult
readvAndTestvAndWritev _ _ Nothing _ = throw MissingUploadSecret
readvAndTestvAndWritev _ _ (Just []) _ = throw MissingUploadSecret
readvAndTestvAndWritev backend storageIndex (Just (Write secret : _)) vectors =
liftIO (Backend.readvAndTestvAndWritev backend storageIndex secret vectors)
readvAndTestvAndWritev backend storageIndex (Just (_ : ss)) vectors =
readvAndTestvAndWritev backend storageIndex (Just ss) vectors
readMutableShare :: Backend.Backend b => b -> StorageIndex -> ShareNumber -> QueryRange -> Handler ShareData
readMutableShare backend storage_index share_numbers params =
liftIO (Backend.readMutableShare backend storage_index share_numbers params)
getMutableShareNumbers :: Backend.Backend b => b -> StorageIndex -> Handler (CBORSet ShareNumber)
getMutableShareNumbers backend storage_index =
liftIO (Backend.getMutableShareNumbers backend storage_index)
adviseCorruptMutableShare :: Backend.Backend b => b -> StorageIndex -> ShareNumber -> CorruptionDetails -> Handler ()
adviseCorruptMutableShare backend storage_index share_number details =
liftIO (Backend.adviseCorruptMutableShare backend storage_index share_number details)
data MisconfiguredTLS = MisconfiguredTLS
deriving (Show)
instance Exception MisconfiguredTLS
data StorageServerConfig = StorageServerConfig
{ storagePath :: FilePath
, listenPort :: Port
, certificate :: Maybe FilePath
, key :: Maybe FilePath
}
deriving (Show, Eq)
app :: Backend.Backend b => b -> Application
app backend =
serve api storageServer
where
storageServer :: Server StorageAPI
storageServer =
version backend
:<|> renewLease backend
:<|> createImmutableStorageIndex backend
:<|> writeImmutableShare backend
:<|> abortImmutableUpload backend
:<|> readImmutableShare backend
:<|> getImmutableShareNumbers backend
:<|> adviseCorruptImmutableShare backend
:<|> readvAndTestvAndWritev backend
:<|> readMutableShare backend
:<|> getMutableShareNumbers backend
:<|> adviseCorruptMutableShare backend
main :: StorageServerConfig -> IO ()
main config =
run $ app (FilesystemBackend $ storagePath config)
where
settings = setPort (listenPort config) defaultSettings
run a =
case (certificate config, key config) of
(Nothing, Nothing) -> runSettings settings a
(Just c, Just k) -> runTLS (tlsSettings c k) settings a
_ -> throw MisconfiguredTLS