Files
2025-04-25 22:27:39 +01:00

156 lines
3.7 KiB
Haskell

module API
( P2PRCapi(..)
, MapPortRequest(..)
, p2prcAPI
)
where
import System.Directory ( getCurrentDirectory )
import System.Process ( ProcessHandle )
import Data.Aeson ( FromJSON )
import Error
( IOEitherError
)
import JSON
( IPAddressTable(..)
, MapPortResponse(..)
, P2PRCConfig
)
import CLI
( StdInput(..)
, CLIOpt(..)
, eitherErrDecode
, p2prcCmdName
, eitherExecProcess
, eitherExecProcessParser
, spawnProcP2PRC
)
-- import System.Environment (lookupEnv)
-- | Lower level P2PRC Haskell api that exposes basic functionality necessary to joint the network.
data P2PRCapi
= MkP2PRCapi
{ startServer :: IOEitherError ProcessHandle
-- ^ Start server
-- , execInitConfig :: IOEitherError P2PRCConfig
-- ^ Instantiate server configuration
, execListServers :: IOEitherError IPAddressTable
-- ^ List servers in network
, execMapPort :: MapPortRequest -> IOEitherError MapPortResponse
-- ^ Exposes and associates a local TCP port with a remote DNS address
}
-- | This defines the request required to create an association between a TCP socket port and a DNS server in the network. If successful, it makes a resource available in the network.
data MapPortRequest =
MkMapPortRequest -- ^ P2PRC's port allocation request value
Int -- ^ TCP socket number
String -- ^ Network domain name
{-|
This function intiates a pure P2PRC runtime state and builds up a 'P2PRCapi' API instance. It allows a developer to create computing orchestration algorithms using the API primitives.
==== __Example__
The following example show how this function can be used to expose the runtime functionalities:
@
module Main where
import P2PRC
( p2prcAPI
, P2PRCapi(..)
)
main :: IO ()
main =
print "Hello P2PRC"
-- your code logic goes here
where
MkP2PRCapi
{ startServer=startServer
, execMapPort=execMapPort
, execListServers=execListServers
, execInitConfig=execInitConfig
} = p2prcAPI
@
-}
{-# WARNING p2prcAPI "This function is currently unstable because the configuration reading is dependent on the following issue: https://github.com/Akilan1999/p2p-rendering-computation/issues/120" #-}
p2prcAPI :: P2PRCapi
p2prcAPI =
MkP2PRCapi
{ startServer = spawnProcP2PRC p2prcCmdName [ MkOptAtomic "--s" ]
, execListServers =
execProcP2PRCParser [ MkOptAtomic "--ls" ] MkEmptyStdInput
, execMapPort =
\ (MkMapPortRequest portNumber domainName) ->
execProcP2PRCParser
[ MkOptTuple
( "--mp"
, show portNumber
)
, MkOptTuple
( "--dn"
, domainName
)
]
MkEmptyStdInput
-- , execInitConfig = do
-- confInitRes <- execProcP2PRC [ MkOptAtomic "--dc" ] MkEmptyStdInput
-- case confInitRes of
-- (Right _) -> do
-- maybeValue <- lookupEnv "P2PRC"
-- -- TODO: get config file name dynamically
-- --
-- currDirectory <- getCurrentDirectory
-- -- TODO: change values before loading file
-- let fname = currDirectory ++ "/config.json" :: FilePath
-- -- TODO: read config check if file exists
-- configContent <- readFile fname
-- pure $ eitherErrDecode configContent
-- (Left err) -> pure $ Left err
}
where
execProcP2PRCParser ::
FromJSON a =>
[CLIOpt] -> StdInput -> IOEitherError a
execProcP2PRCParser = eitherExecProcessParser p2prcCmdName
-- TODO: GHC question, why does it scope down instead staying generic
-- execProcP2PRC = eitherExecProcess p2prcCmdName