module Network.CoAP.Client
( Request(..)
, Client(..)
, Method(..)
, Response(..)
, ResponseCode(..)
, Option(..)
, OptionString
, MediaType(..)
, createClient
) where
import Network.CoAP.Messaging
import Network.CoAP.Types
import Control.Monad.State
import Control.Concurrent.Async
import Control.Concurrent.STM
import Network.Socket
import Data.ByteString hiding (putStrLn)
import Data.Word
import System.Random
import Network.URI
import Network.CoAP.Internal
data Client = Client {
doRequest :: URI -> Request -> IO Response
, doRawRequest :: Endpoint -> Request -> IO Response
, shutdownClient :: IO () }
createClient :: Transport -> IO Client
createClient transport = do
state <- createMessagingState transport
msgThreads <- startMessaging state
return Client { doRequest = doRequestInternal state
, doRawRequest = doRawRequestInternal state
, shutdownClient = stopClient state msgThreads }
stopClient :: MessagingState -> [Async ()] -> IO ()
stopClient state threads = do
stopMessaging state threads
mapM_ wait threads
generateToken :: Int -> IO [Word8]
generateToken 0 = return []
generateToken len = do
tkn <- randomIO
next <- generateToken (len 1)
return (tkn:next)
doRequestInternal :: MessagingState -> URI -> Request -> IO Response
doRequestInternal state uri (Request method options payload reliable) = do
dest <- createEndpoint uri
let newOpts = createOpts uri
doRawRequestInternal state dest (Request method (options ++ newOpts) payload reliable)
doRawRequestInternal :: MessagingState -> Endpoint -> Request -> IO Response
doRawRequestInternal state dest (Request method options payload reliable) = do
tokenLen <- randomRIO (0, 8)
token <- generateToken tokenLen
let msg = Message { messageVersion = 1
, messageType = if reliable then CON else NON
, messageCode = CodeRequest method
, messageId = 0
, messageToken = pack token
, messageOptions = options
, messagePayload = payload }
sendRequest msg dest state
responseCtx <- recvResponse msg dest state
let (Message _ _ (CodeResponse rCode) _ _ opts pload) = message responseCtx
return Response { responseCode = rCode
, responseOptions = opts
, responsePayload = pload }