{-# LANGUAGE RecordWildCards #-}

module HOCD
  ( runOCD
  , module HOCD.Error
  , module HOCD.Monad
  , module HOCD.Types
  ) where

import Control.Monad.Catch (MonadMask)
import Control.Monad.IO.Class (MonadIO(liftIO))
import Data.Default.Class (Default(def))

import qualified Control.Monad.Catch
import qualified Network.Socket

import HOCD.Error
import HOCD.Monad
import HOCD.Types

-- | Run OpenOCD client
-- with defaults ("127.0.0.1:6666")
runOCD
  :: ( MonadIO m
     , MonadMask m
     )
  => OCDT m a
  -> m (Either OCDError a)
runOCD :: forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
OCDT m a -> m (Either OCDError a)
runOCD = forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
OCDConfig -> OCDT m a -> m (Either OCDError a)
runOCDConfig forall a. Default a => a
def

-- | Run OpenOCD client with @OCDConfig@
-- allowing to set custom host and port
runOCDConfig
  :: ( MonadIO m
     , MonadMask m
     )
  => OCDConfig
  -> OCDT m a
  -> m (Either OCDError a)
runOCDConfig :: forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
OCDConfig -> OCDT m a -> m (Either OCDError a)
runOCDConfig OCDConfig{Int
String
ocdPort :: OCDConfig -> Int
ocdHost :: OCDConfig -> String
ocdPort :: Int
ocdHost :: String
..} OCDT m a
act = do
  [AddrInfo]
addrInfo <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Maybe AddrInfo -> Maybe String -> Maybe String -> IO [AddrInfo]
Network.Socket.getAddrInfo
    (forall a. a -> Maybe a
Just AddrInfo
Network.Socket.defaultHints)
    (forall a. a -> Maybe a
Just String
ocdHost)
    (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Int
ocdPort)

  case [AddrInfo]
addrInfo of
    (AddrInfo
sockAddr:[AddrInfo]
_) ->
      forall (m :: * -> *) a c b.
MonadMask m =>
m a -> (a -> m c) -> (a -> m b) -> m b
Control.Monad.Catch.bracket
        (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
          forall a b. (a -> b) -> a -> b
$ Family -> SockAddr -> IO Socket
open
              (AddrInfo -> Family
Network.Socket.addrFamily AddrInfo
sockAddr)
              (AddrInfo -> SockAddr
Network.Socket.addrAddress AddrInfo
sockAddr)
        )
        (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> IO ()
Network.Socket.close)
        (\Socket
sock -> forall (m :: * -> *) a.
Monad m =>
Socket -> OCDT m a -> m (Either OCDError a)
runOCDT Socket
sock OCDT m a
act)
    [AddrInfo]
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. a -> Either a b
Left OCDError
OCDError_GetAddrInfoFailed)
  where
    open :: Family -> SockAddr -> IO Socket
open Family
sockFamily SockAddr
sockAddr = do
      Socket
soc <-
        Family -> SocketType -> ProtocolNumber -> IO Socket
Network.Socket.socket
          Family
sockFamily
          SocketType
Network.Socket.Stream
          ProtocolNumber
Network.Socket.defaultProtocol
      Socket -> SockAddr -> IO ()
Network.Socket.connect Socket
soc SockAddr
sockAddr
      forall (f :: * -> *) a. Applicative f => a -> f a
pure Socket
soc