packages feed

skylark-client-0.1.3: src/Network/Skylark/Client.hs

{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}

module Network.Skylark.Client
  ( runSkylark
  , runSkylark'
  ) where

import Control.Concurrent.Async.Lifted
import Control.Concurrent.STM
import Data.Conduit
import Data.Conduit.TQueue
import Network.HTTP.Conduit
import Network.HTTP.Types
import Network.HTTP.Types.Header
import Preamble

{-# ANN module ("HLint: ignore Redundant flip"::String) #-}

-- | Device-Uid Header
--
hDevice :: HeaderName
hDevice = "Device-Uid"

-- | SBPv2 Content-Type
--
sbpContentType :: ByteString
sbpContentType = "application/vnd.swiftnav.broker.v1+sbp2"

-- | Download data from Skylark to sink.
--
download :: MonadIO m => ByteString -> Manager -> Request -> TBQueue ByteString -> m ()
download device manager request queue =
  liftIO $ runResourceT $ do
    response <- flip http manager request
      { method = methodGet
      , requestHeaders =
          [ (hAccept, sbpContentType)
          , (hDevice, device)
          , (hPragma, "proxy")
          ]
      }
    responseBody response $$+- sinkTBQueue queue


-- | Upload data to Skylark from source.
--
upload :: MonadIO m => ByteString -> Manager -> Request -> TBQueue ByteString -> m ()
upload device manager request queue =
  void $ flip httpLbs manager request
    { method      = methodPut
    , requestHeaders =
        [ (hContentType, sbpContentType)
        , (hDevice, device)
        ]
    , requestBody = requestBodySourceChunked $ sourceTBQueue queue
    }

-- | Run Skylark client with connections concurrent.
--
runSkylark :: MonadControl m => String -> ByteString -> Source m ByteString -> Sink ByteString m () -> m ()
runSkylark url device source sink = do
  manager   <- liftIO $ newManager tlsManagerSettings
  request   <- parseRequest url
  upQueue   <- liftIO $ atomically $ newTBQueue 8192
  downQueue <- liftIO $ atomically $ newTBQueue 8192
  void $ concurrently
    (concurrently (download device manager request downQueue) (sourceTBQueue downQueue $$ sink))
    (concurrently (source $$ sinkTBQueue upQueue) (upload device manager request upQueue))

-- | Run Skylark client with connections racing.
--
runSkylark' :: MonadControl m => String -> ByteString -> Source m ByteString -> Sink ByteString m () -> m ()
runSkylark' url device source sink = do
  manager   <- liftIO $ newManager tlsManagerSettings
  request   <- parseRequest url
  upQueue   <- liftIO $ atomically $ newTBQueue 8192
  downQueue <- liftIO $ atomically $ newTBQueue 8192
  race_
    (race_ (download device manager request downQueue) (sourceTBQueue downQueue $$ sink))
    (race_ (source $$ sinkTBQueue upQueue) (upload device manager request upQueue))