krpc- KRPC protocol implementation

Safe HaskellNone




This module provides safe remote procedure call. One important point is exceptions and errors, so to be able handle them properly we need to investigate a bit about how this all works. Internally, in order to make method invokation KRPC makes the following steps:

  • Caller serialize arguments to bencoded bytestrings;
  • Caller send bytestring data over UDP to the callee;
  • Callee receive and decode arguments to the method and method name. If it can't decode then it send ProtocolError back to the caller;
  • Callee search for the method name in the method table. If it not present in the table then callee send MethodUnknown back to the caller;
  • Callee check if argument names match. If not it send ProtocolError back;
  • Callee make the actuall call to the plain old haskell function. If the function throw exception then callee send ServerError back.
  • Callee serialize result of the function to bencoded bytestring.
  • Callee encode result to bencoded bytestring and send it back to the caller.
  • Caller check if return values names match with the signature it called in the first step.
  • Caller extracts results and finally return results of the procedure call as ordinary haskell values.

If every other error occurred then caller get the GenericError. All errors returned by callee are throwed as ordinary haskell exceptions at caller side. Also note that both caller and callee use plain UDP, so KRPC is unreliable.

For async query use async package.

For protocol details see Network.KRPC.Message module.



data Method param result Source

Method datatype used to describe method name, parameters and return values of procedure. Client use a method to invoke, server implements the method to make the actual work.

We use the following fantom types to ensure type-safiety:

  • param: Type of method parameters.
  • result: Type of return value of the method.


Eq (Method param result) 
Ord (Method param result) 
(Typeable a, Typeable b) => Show (Method a b)


show (Method "concat" :: [Int] Int) == "concat :: [Int] -> Int"
IsString (Method param result) 
BEncode (Method param result) 

class (Typeable req, BEncode req, Typeable resp, BEncode resp) => KRPC req resp | req -> resp whereSource

In order to perform or handle KRPC query you need to provide corresponding KRPC class.


   data Ping = Ping Text deriving BEncode
   data Pong = Pong Text deriving BEncode

instance KRPC Ping Pong where
     method = "ping"


method :: Method req respSource

Method name. Default implementation uses lowercased req datatype name.



data QueryFailure Source

Used to signal query errors.



unable to send query;

QueryFailed ErrorCode Text

remote node return error;


remote node not responding.

query :: forall h m a b. (MonadKRPC h m, KRPC a b) => SockAddr -> a -> m bSource

Enqueue query to the given node.

This function should throw QueryFailure exception if quered node respond with error message or the query timeout expires.

getQueryCount :: MonadKRPC h m => m IntSource

How many times query call have been performed.


data HandlerFailure Source

Used to signal protocol errors.



for e.g.: node calls herself;

InvalidParameter Text

for e.g.: bad session token.

type Handler h = (MethodName, HandlerBody h)Source

Handler is a function which will be invoked then some remote node querying this node.

handler :: forall h a b. (KRPC a b, Monad h) => (SockAddr -> a -> h b) -> Handler hSource

Make handler from handler function. Any thrown exception will be supressed and send over the wire back to the querying node.

If the handler make some query normally it should handle corresponding QueryFailures.


class (MonadBaseControl IO m, MonadLogger m, MonadIO m) => MonadKRPC h m | m -> h whereSource

A monad which can perform or handle queries.


getManager :: m (Manager h)Source

Ask for manager.

liftHandler :: h a -> m aSource

Can be used to add logging for instance.


data Options Source

RPC manager options.




optSeedTransaction :: !Int

Initial TransactionId incremented with each query;

optQueryTimeout :: !Int

Time to wait for response from remote node, in seconds.

optMaxMsgSize :: !Int

Maximum number of bytes to receive.


Eq Options 
Show Options 
Default Options

Permissive defaults.

def :: Default a => a

The default value for this type.

data Manager h Source

Keep track pending queries made by this node and handle queries made by remote nodes.




:: Options

various protocol options;

-> SockAddr

address to listen on;

-> [Handler h]

handlers to run on incoming queries.

-> IO (Manager h)

new rpc manager.

Bind socket to the specified address. To enable query handling run listen.

closeManager :: Manager m -> IO ()Source

Unblock all pending calls and close socket.

withManager :: Options -> SockAddr -> [Handler h] -> (Manager h -> IO a) -> IO aSource

Normally you should use Control.Monad.Trans.Resource.allocate function.

isActive :: Manager m -> IO BoolSource

Check if the manager is still active. Manager becomes active until closeManager called.

listen :: MonadKRPC h m => m ()Source

Should be run before any query, otherwise they will never succeed.


data ErrorCode Source

Types of RPC errors.



Some error doesn't fit in any other category.


Occur when server fail to process procedure call.


Malformed packet, invalid arguments or bad token.


Occur when client trying to call method server don't know.