summaryrefslogtreecommitdiff
path: root/src/Network/KRPC/Manager.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/KRPC/Manager.hs')
-rw-r--r--src/Network/KRPC/Manager.hs43
1 files changed, 17 insertions, 26 deletions
diff --git a/src/Network/KRPC/Manager.hs b/src/Network/KRPC/Manager.hs
index e7f0563b..b1e93101 100644
--- a/src/Network/KRPC/Manager.hs
+++ b/src/Network/KRPC/Manager.hs
@@ -76,6 +76,7 @@ import Data.Text as T
76import Data.Text.Encoding as T 76import Data.Text.Encoding as T
77import Data.Tuple 77import Data.Tuple
78import Data.Typeable 78import Data.Typeable
79import Network.RPC
79import Network.KRPC.Message 80import Network.KRPC.Message
80import Network.KRPC.Method 81import Network.KRPC.Method
81import Network.Socket hiding (listen) 82import Network.Socket hiding (listen)
@@ -136,11 +137,11 @@ type CallId = (TransactionId, SockAddr)
136type CallRes = MVar (KQueryArgs, KResult) -- (raw response, decoded response) 137type CallRes = MVar (KQueryArgs, KResult) -- (raw response, decoded response)
137type PendingCalls = IORef (Map CallId CallRes) 138type PendingCalls = IORef (Map CallId CallRes)
138 139
139type HandlerBody h = SockAddr -> KQueryArgs -> h (Either String KQueryArgs) 140type HandlerBody h msg v = SockAddr -> msg v -> h (Either String v)
140 141
141-- | Handler is a function which will be invoked then some /remote/ 142-- | Handler is a function which will be invoked then some /remote/
142-- node querying /this/ node. 143-- node querying /this/ node.
143type Handler h = (MethodName, HandlerBody h) 144type Handler h msg v = (MethodName, HandlerBody h msg v)
144 145
145-- | Keep track pending queries made by /this/ node and handle queries 146-- | Keep track pending queries made by /this/ node and handle queries
146-- made by /remote/ nodes. 147-- made by /remote/ nodes.
@@ -150,7 +151,7 @@ data Manager h = Manager
150 , listenerThread :: !(MVar ThreadId) 151 , listenerThread :: !(MVar ThreadId)
151 , transactionCounter :: {-# UNPACK #-} !TransactionCounter 152 , transactionCounter :: {-# UNPACK #-} !TransactionCounter
152 , pendingCalls :: {-# UNPACK #-} !PendingCalls 153 , pendingCalls :: {-# UNPACK #-} !PendingCalls
153 , handlers :: [Handler h] 154 , handlers :: [Handler h KMessageOf BValue]
154 } 155 }
155 156
156-- | A monad which can perform or handle queries. 157-- | A monad which can perform or handle queries.
@@ -182,10 +183,10 @@ sockAddrFamily (SockAddrCan _ ) = AF_CAN
182 183
183-- | Bind socket to the specified address. To enable query handling 184-- | Bind socket to the specified address. To enable query handling
184-- run 'listen'. 185-- run 'listen'.
185newManager :: Options -- ^ various protocol options; 186newManager :: Options -- ^ various protocol options;
186 -> SockAddr -- ^ address to listen on; 187 -> SockAddr -- ^ address to listen on;
187 -> [Handler h] -- ^ handlers to run on incoming queries. 188 -> [Handler h KMessageOf BValue] -- ^ handlers to run on incoming queries.
188 -> IO (Manager h) -- ^ new rpc manager. 189 -> IO (Manager h) -- ^ new rpc manager.
189newManager opts @ Options {..} servAddr handlers = do 190newManager opts @ Options {..} servAddr handlers = do
190 validateOptions opts 191 validateOptions opts
191 sock <- bindServ 192 sock <- bindServ
@@ -217,7 +218,7 @@ isActive Manager {..} = liftIO $ isBound sock
217 218
218-- | Normally you should use Control.Monad.Trans.Resource.allocate 219-- | Normally you should use Control.Monad.Trans.Resource.allocate
219-- function. 220-- function.
220withManager :: Options -> SockAddr -> [Handler h] 221withManager :: Options -> SockAddr -> [Handler h KMessageOf BValue]
221 -> (Manager h -> IO a) -> IO a 222 -> (Manager h -> IO a) -> IO a
222withManager opts addr hs = bracket (newManager opts addr hs) closeManager 223withManager opts addr hs = bracket (newManager opts addr hs) closeManager
223 224
@@ -408,35 +409,25 @@ prettyQF e = T.encodeUtf8 $ "handler fail while performing query: "
408-- If the handler make some 'query' normally it /should/ handle 409-- If the handler make some 'query' normally it /should/ handle
409-- corresponding 'QueryFailure's. 410-- corresponding 'QueryFailure's.
410-- 411--
411handler :: forall h a b. (KRPC a b, Monad h) 412handler :: forall h a b msg. (KRPC a b, Applicative h, Functor msg)
412 => (SockAddr -> a -> h b) -> Handler h 413 => Messaging msg TransactionId (Envelope a b) -> (SockAddr -> a -> h b) -> Handler h msg (Envelope a b)
413handler body = (name, wrapper) 414handler msging body = (name, wrapper)
414 where 415 where
415 Method name = method :: Method a b 416 Method name = method :: Method a b
416 wrapper addr args = 417 wrapper addr args =
417#ifdef VERSION_bencoding 418 case unseal $ messagePayload msging args of
418 case fromBEncode args of 419 Left e -> pure $ Left e
419#else 420 Right a -> Right . seal <$> body addr a
420 case S.decode args of
421#endif
422 Left e -> return $ Left e
423 Right a -> do
424 r <- body addr a
425#ifdef VERSION_bencoding
426 return $ Right $ toBEncode r
427#else
428 return $ Right $ S.encode r
429#endif
430 421
431runHandler :: MonadKRPC h m 422runHandler :: MonadKRPC h m
432 => HandlerBody h -> SockAddr -> KQuery -> m KResult 423 => HandlerBody h KMessageOf BValue -> SockAddr -> KQuery -> m KResult
433runHandler h addr m = Lifted.catches wrapper failbacks 424runHandler h addr m = Lifted.catches wrapper failbacks
434 where 425 where
435 signature = querySignature (queryMethod m) (queryId m) addr 426 signature = querySignature (queryMethod m) (queryId m) addr
436 427
437 wrapper = do 428 wrapper = do
438 $(logDebugS) "handler.quered" signature 429 $(logDebugS) "handler.quered" signature
439 result <- liftHandler (h addr (queryArgs m)) 430 result <- liftHandler (h addr (Q m))
440 431
441 case result of 432 case result of
442 Left msg -> do 433 Left msg -> do