diff options
-rw-r--r-- | bench/Main.hs | 2 | ||||
-rw-r--r-- | krpc.cabal | 1 | ||||
-rw-r--r-- | src/Network/KRPC.hs | 3 | ||||
-rw-r--r-- | src/Network/KRPC/Manager.hs | 60 | ||||
-rw-r--r-- | tests/Network/KRPCSpec.hs | 7 |
5 files changed, 57 insertions, 16 deletions
diff --git a/bench/Main.hs b/bench/Main.hs index 13727ff9..8466f4a3 100644 --- a/bench/Main.hs +++ b/bench/Main.hs | |||
@@ -22,7 +22,7 @@ addr :: SockAddr | |||
22 | addr = SockAddrInet 6000 (256 * 256 * 256 + 127) | 22 | addr = SockAddrInet 6000 (256 * 256 * 256 + 127) |
23 | 23 | ||
24 | main :: IO () | 24 | main :: IO () |
25 | main = withManager addr [echo] $ \ m -> (`runReaderT` m) $ do | 25 | main = withManager def addr [echo] $ \ m -> (`runReaderT` m) $ do |
26 | listen | 26 | listen |
27 | liftIO $ defaultMain (benchmarks m) | 27 | liftIO $ defaultMain (benchmarks m) |
28 | where | 28 | where |
@@ -46,6 +46,7 @@ library | |||
46 | build-depends: base == 4.* | 46 | build-depends: base == 4.* |
47 | , bytestring >= 0.10 | 47 | , bytestring >= 0.10 |
48 | , text >= 0.11 | 48 | , text >= 0.11 |
49 | , data-default-class | ||
49 | , lifted-base >= 0.1.1 | 50 | , lifted-base >= 0.1.1 |
50 | , transformers >= 0.2 | 51 | , transformers >= 0.2 |
51 | , mtl | 52 | , mtl |
diff --git a/src/Network/KRPC.hs b/src/Network/KRPC.hs index a1767161..7c02702c 100644 --- a/src/Network/KRPC.hs +++ b/src/Network/KRPC.hs | |||
@@ -62,6 +62,8 @@ module Network.KRPC | |||
62 | 62 | ||
63 | -- * Manager | 63 | -- * Manager |
64 | , MonadKRPC (..) | 64 | , MonadKRPC (..) |
65 | , Options (..) | ||
66 | , def | ||
65 | , Manager | 67 | , Manager |
66 | , newManager | 68 | , newManager |
67 | , closeManager | 69 | , closeManager |
@@ -76,6 +78,7 @@ module Network.KRPC | |||
76 | , SockAddr (..) | 78 | , SockAddr (..) |
77 | ) where | 79 | ) where |
78 | 80 | ||
81 | import Data.Default.Class | ||
79 | import Network.KRPC.Message | 82 | import Network.KRPC.Message |
80 | import Network.KRPC.Method | 83 | import Network.KRPC.Method |
81 | import Network.KRPC.Manager | 84 | import Network.KRPC.Manager |
diff --git a/src/Network/KRPC/Manager.hs b/src/Network/KRPC/Manager.hs index 4d1cfb69..7edcf72d 100644 --- a/src/Network/KRPC/Manager.hs +++ b/src/Network/KRPC/Manager.hs | |||
@@ -18,6 +18,7 @@ | |||
18 | module Network.KRPC.Manager | 18 | module Network.KRPC.Manager |
19 | ( -- * Manager | 19 | ( -- * Manager |
20 | MonadKRPC (..) | 20 | MonadKRPC (..) |
21 | , Options (..) | ||
21 | , Manager | 22 | , Manager |
22 | , newManager | 23 | , newManager |
23 | , closeManager | 24 | , closeManager |
@@ -43,6 +44,7 @@ import Data.BEncode as BE | |||
43 | import Data.ByteString as BS | 44 | import Data.ByteString as BS |
44 | import Data.ByteString.Char8 as BC | 45 | import Data.ByteString.Char8 as BC |
45 | import Data.ByteString.Lazy as BL | 46 | import Data.ByteString.Lazy as BL |
47 | import Data.Default.Class | ||
46 | import Data.IORef | 48 | import Data.IORef |
47 | import Data.List as L | 49 | import Data.List as L |
48 | import Data.Map as M | 50 | import Data.Map as M |
@@ -58,6 +60,41 @@ import System.IO.Error | |||
58 | import System.Timeout | 60 | import System.Timeout |
59 | 61 | ||
60 | 62 | ||
63 | {----------------------------------------------------------------------- | ||
64 | -- Options | ||
65 | -----------------------------------------------------------------------} | ||
66 | |||
67 | -- | RPC manager options. | ||
68 | data Options = Options | ||
69 | { -- | Initial 'TransactionId' incremented with each 'query'; | ||
70 | optSeedTransaction :: Int | ||
71 | |||
72 | -- | Time to wait for response from remote node, in seconds. | ||
73 | , optQueryTimeout :: Int | ||
74 | } deriving (Show, Eq) | ||
75 | |||
76 | defaultSeedTransaction :: Int | ||
77 | defaultSeedTransaction = 0 | ||
78 | |||
79 | defaultQueryTimeout :: Int | ||
80 | defaultQueryTimeout = 120 | ||
81 | |||
82 | -- | Permissive defaults. | ||
83 | instance Default Options where | ||
84 | def = Options | ||
85 | { optSeedTransaction = defaultSeedTransaction | ||
86 | , optQueryTimeout = defaultQueryTimeout | ||
87 | } | ||
88 | |||
89 | validateOptions :: Options -> IO () | ||
90 | validateOptions Options {..} | ||
91 | | optQueryTimeout < 1 = throwIO (userError "non-positive query timeout") | ||
92 | | otherwise = return () | ||
93 | |||
94 | {----------------------------------------------------------------------- | ||
95 | -- Options | ||
96 | -----------------------------------------------------------------------} | ||
97 | |||
61 | type KResult = Either KError KResponse | 98 | type KResult = Either KError KResponse |
62 | 99 | ||
63 | type TransactionCounter = IORef Int | 100 | type TransactionCounter = IORef Int |
@@ -108,23 +145,19 @@ sockAddrFamily (SockAddrInet _ _ ) = AF_INET | |||
108 | sockAddrFamily (SockAddrInet6 _ _ _ _) = AF_INET6 | 145 | sockAddrFamily (SockAddrInet6 _ _ _ _) = AF_INET6 |
109 | sockAddrFamily (SockAddrUnix _ ) = AF_UNIX | 146 | sockAddrFamily (SockAddrUnix _ ) = AF_UNIX |
110 | 147 | ||
111 | seedTransaction :: Int | ||
112 | seedTransaction = 0 | ||
113 | |||
114 | defaultQueryTimeout :: Int | ||
115 | defaultQueryTimeout = 120 | ||
116 | |||
117 | -- | Bind socket to the specified address. To enable query handling | 148 | -- | Bind socket to the specified address. To enable query handling |
118 | -- run 'listen'. | 149 | -- run 'listen'. |
119 | newManager :: SockAddr -- ^ address to listen on; | 150 | newManager :: Options -- ^ various protocol options; |
151 | -> SockAddr -- ^ address to listen on; | ||
120 | -> [Handler h] -- ^ handlers to run on incoming queries. | 152 | -> [Handler h] -- ^ handlers to run on incoming queries. |
121 | -> IO (Manager h) -- ^ new manager. | 153 | -> IO (Manager h) -- ^ new rpc manager. |
122 | newManager servAddr handlers = do | 154 | newManager opts @ Options {..} servAddr handlers = do |
155 | validateOptions opts | ||
123 | sock <- bindServ | 156 | sock <- bindServ |
124 | tref <- newEmptyMVar | 157 | tref <- newEmptyMVar |
125 | tran <- newIORef seedTransaction | 158 | tran <- newIORef optSeedTransaction |
126 | calls <- newIORef M.empty | 159 | calls <- newIORef M.empty |
127 | return $ Manager sock defaultQueryTimeout tref tran calls handlers | 160 | return $ Manager sock optQueryTimeout tref tran calls handlers |
128 | where | 161 | where |
129 | bindServ = do | 162 | bindServ = do |
130 | let family = sockAddrFamily servAddr | 163 | let family = sockAddrFamily servAddr |
@@ -143,8 +176,9 @@ closeManager Manager {..} = do | |||
143 | 176 | ||
144 | -- | Normally you should use Control.Monad.Trans.Resource.allocate | 177 | -- | Normally you should use Control.Monad.Trans.Resource.allocate |
145 | -- function. | 178 | -- function. |
146 | withManager :: SockAddr -> [Handler h] -> (Manager h -> IO a) -> IO a | 179 | withManager :: Options -> SockAddr -> [Handler h] |
147 | withManager addr hs = bracket (newManager addr hs) closeManager | 180 | -> (Manager h -> IO a) -> IO a |
181 | withManager opts addr hs = bracket (newManager opts addr hs) closeManager | ||
148 | 182 | ||
149 | {----------------------------------------------------------------------- | 183 | {----------------------------------------------------------------------- |
150 | -- Logging | 184 | -- Logging |
diff --git a/tests/Network/KRPCSpec.hs b/tests/Network/KRPCSpec.hs index 7f5b2794..e73b1ec0 100644 --- a/tests/Network/KRPCSpec.hs +++ b/tests/Network/KRPCSpec.hs | |||
@@ -20,18 +20,21 @@ handlers = | |||
20 | instance MonadLogger IO where | 20 | instance MonadLogger IO where |
21 | monadLoggerLog _ _ _ _ = return () | 21 | monadLoggerLog _ _ _ _ = return () |
22 | 22 | ||
23 | opts :: Options | ||
24 | opts = def { optQueryTimeout = 1 } | ||
25 | |||
23 | spec :: Spec | 26 | spec :: Spec |
24 | spec = do | 27 | spec = do |
25 | describe "query" $ do | 28 | describe "query" $ do |
26 | it "run handlers" $ do | 29 | it "run handlers" $ do |
27 | let int = 0xabcd :: Int | 30 | let int = 0xabcd :: Int |
28 | (withManager servAddr handlers $ runReaderT $ do | 31 | (withManager opts servAddr handlers $ runReaderT $ do |
29 | listen | 32 | listen |
30 | query servAddr (Echo int)) | 33 | query servAddr (Echo int)) |
31 | `shouldReturn` Echo int | 34 | `shouldReturn` Echo int |
32 | 35 | ||
33 | it "throw timeout exception" $ do | 36 | it "throw timeout exception" $ do |
34 | (withManager servAddr handlers $ runReaderT $ do | 37 | (withManager opts servAddr handlers $ runReaderT $ do |
35 | query servAddr (Echo (0xabcd :: Int)) | 38 | query servAddr (Echo (0xabcd :: Int)) |
36 | ) | 39 | ) |
37 | `shouldThrow` (== KError GenericError "timeout expired" "0") | 40 | `shouldThrow` (== KError GenericError "timeout expired" "0") |