module Network.Socketson.SessionStore where -- intern: import Network.Socketson.ServerState import Network.Socketson.ProtocolException -- mvar: import Control.Concurrent.MVar -- data: import qualified Data.Serialize as BIN import qualified Data.ByteString as BS import Data.Default -- leveldb: import Database.LevelDB -- either transformer: import Control.Monad.Trans.Either import Data.Either.Combinators (mapLeft) {----------------- Session Store Stores session data in a levelDB, hashed under generated session keys. The handle gets generated whenever work has to be done; the path to the levelDB files are needed. -} {-| Saves given session data (which can be anything which is serializable) under given key, based on the given server state. saveSessionData serverState key sessionData -} saveSessionData :: (BIN.Serialize a) => ServerState -> BS.ByteString -> a -> IO () saveSessionData state key dat = runResourceT (do db <- open (storePath state) defaultOptions { createIfMissing = True } put db def key (BIN.encode dat) ) {-| Restores session data which was saved in the session store before, saved under given key, wrapped in a 'Maybe' monad. Returns 'Nothing' if no data was found under given key. -} restoreSessionData :: (BIN.Serialize a) => ServerState -> BS.ByteString -> EitherT ProtocolException IO a restoreSessionData state key = do res <- runResourceT (do db <- open (storePath state) defaultOptions { createIfMissing = True } get db def key) case res of Just x -> hoistEither $ mapLeft (SessionStoreCorruptAt key) (BIN.decode x) Nothing -> left (InvalidSessionKey key)