module Database.Bolt.Transport
( Transport(..)
, put
, get
, getE
, handshake
, BoltProtocol
, OfferProtocols(..)
, noProto
) where
import qualified Data.ByteString as BS
import Data.Monoid
import Data.Serialize.Get
import Data.Serialize.Put
import Data.Text as T
import Data.Word
import Database.Bolt.Exception
class Transport t where
send :: t -> BS.ByteString -> IO ()
recv :: t -> Int -> IO BS.ByteString
close :: t -> IO ()
sendMany :: t -> [BS.ByteString] -> IO ()
sendMany conn = mapM_ (send conn)
put :: Transport t => t -> Put -> IO ()
put conn = send conn . runPut
get :: Transport t => t -> Int -> Get a -> IO a
get conn n g = getE conn n g >>= either bad return
where
bad e = transportErr $ "Bad data received: " <> T.pack e
getE :: Transport t => t -> Int -> Get a -> IO (Either String a)
getE conn n g = runGet g <$> recv conn n
type BoltProtocol = Word32
noProto :: BoltProtocol
noProto = 0
data OfferProtocols = OfferProtocols BoltProtocol BoltProtocol BoltProtocol BoltProtocol
deriving (Show, Eq, Ord)
handshake :: Transport t => t -> OfferProtocols -> IO BoltProtocol
handshake conn offer = do
put conn (gogobolt >> offerProtocols offer)
get conn 4 agreedProtocol
gogobolt :: Put
gogobolt = mapM_ putWord8 [0x60, 0x60, 0xb0, 0x17]
offerProtocols :: Putter OfferProtocols
offerProtocols (OfferProtocols p1 p2 p3 p4) = mapM_ offerProtocol [p1, p2, p3, p4]
where
offerProtocol = putWord32be
agreedProtocol :: Get BoltProtocol
agreedProtocol = getWord32be