{- Copyright 2016 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} {-# LANGUAGE OverloadedStrings #-} module Storage.Network (Server(..), networkServers, networkStorage) where import Types import Types.Storage import HTTP import HTTP.Client import Servant.Client import Network.Wai.Handler.Warp (Port) import Network.HTTP.Client (Manager, newManager, defaultManagerSettings) import Control.Monad.Trans.Except (ExceptT, runExceptT) data Server = Server { serverName :: String , serverPort :: Port } serverUrl :: Server -> BaseUrl serverUrl srv = BaseUrl Http (serverName srv) (serverPort srv) "" networkServers :: IO [Server] networkServers = return [ Server "localhost" 8080 , Server "localhost" 8080 , Server "localhost" 8080 ] networkStorage :: Server -> Storage networkStorage server = Storage { storeShare = store server , retrieveShare = retrieve server , obscureShares = obscure server , countShares = count server , moveShares = move server } store :: Server -> StorableObjectIdent -> Share -> IO StoreResult store srv i (Share _n o) = serverRequest srv StoreFailure id $ \pow -> putObject i pow o retrieve :: Server -> ShareNum -> StorableObjectIdent -> IO RetrieveResult retrieve srv n i = serverRequest srv RetrieveFailure (RetrieveSuccess . Share n) $ getObject i -- | Servers should automatically obscure, so do nothing. -- (Could upload chaff.) obscure :: Server -> IO ObscureResult obscure _ = return ObscureSuccess count :: Server -> IO CountResult count srv = serverRequest srv CountFailure id countObjects -- | Not needed for servers. move :: Server -> Storage -> IO () move _ _ = error "move is not implemented for servers" serverRequest :: Server -> (String -> a) -> (r -> a) -> (Maybe ProofOfWork -> Manager -> BaseUrl -> ExceptT ServantError IO (ProofOfWorkRequirement r)) -> IO a serverRequest srv onerr onsuccess a = go Nothing =<< newManager defaultManagerSettings where url = serverUrl srv go pow manager = do res <- runExceptT $ a pow manager url case res of Left err -> return $ onerr $ "server failure: " ++ show err Right (Result r) -> return $ onsuccess r Right needpow -> error "NEEDPOW" -- loop with pow