---
title: llarp/rpc/rpc_request_decorators.hpp

---

# llarp/rpc/rpc_request_decorators.hpp



## Namespaces

| Name           |
| -------------- |
| **[tools](Namespaces/namespacetools.md)**  |
| **[llarp](Namespaces/namespacellarp.md)** <br>[crypto.hpp] |
| **[llarp::rpc](Namespaces/namespacellarp_1_1rpc.md)**  |

## Classes

|                | Name           |
| -------------- | -------------- |
| struct | **[tools::type_list](Classes/structtools_1_1type__list.md)**  |
| struct | **[llarp::rpc::RPCRequest](Classes/structllarp_1_1rpc_1_1RPCRequest.md)**  |
| struct | **[llarp::rpc::NoArgs](Classes/structllarp_1_1rpc_1_1NoArgs.md)**  |
| struct | **[llarp::rpc::Immediate](Classes/structllarp_1_1rpc_1_1Immediate.md)**  |




## Source code

```cpp
#pragma once

#include "json_binary_proxy.hpp"
#include "json_bt.hpp"
#include <nlohmann/json_fwd.hpp>
#include <string_view>
#include <llarp/config/config.hpp>
#include <oxenmq/oxenmq.h>
#include <oxenmq/address.h>
#include <oxen/log/omq_logger.hpp>

namespace tools
{
  //  Type wrapper that contains an arbitrary list of types.
  template <typename...>
  struct type_list
  {};
}  // namespace tools

namespace llarp::rpc
{
  //  Base class that all RPC requests will expand for each endpoint type
  struct RPCRequest
  {
   private:
    bool bt = false;

   public:
    //  Returns true if response is bt-encoded, and false for json
    //  Note: do not set value
    bool
    is_bt() const
    {
      return bt;
    }

    //  Callable method to indicate request is bt-encoded
    void
    set_bt()
    {
      bt = true;
      response_b64.format = llarp::rpc::json_binary_proxy::fmt::bt;
      response_hex.format = llarp::rpc::json_binary_proxy::fmt::bt;
    }

    //  Invoked if this.replier is still present. If it is "stolen" by endpoint (moved from
    //  RPC struct), then endpoint handles sending reply
    void
    send_response()
    {
      replier->reply(
          is_bt() ? oxenc::bt_serialize(json_to_bt(std::move(response))) : response.dump());
    }

    void
    send_response(nlohmann::json _response)
    {
      response = std::move(_response);
      send_response();
    }

    //  Response Data:
    //  bt-encoded are converted in real-time
    //    - bool becomes 0 or 1
    //    - key:value where value == null are omitted
    //    - other nulls will raise an exception if found in json
    //    - no doubles
    //      - to store doubles: encode bt in endpoint-specific way
    //    - binary strings will fail json serialization; caller must
    //
    //        std::string binary = some_binary_data();
    //        request.response["binary_value"] = is_bt ? binary : oxenmq::to_hex(binary)
    //
    nlohmann::json response;

    //  Proxy Object:
    //  Sets binary data in "response"
    //    - if return type is json, encodes as hex
    //    - if return type is bt, then binary is untouched
    //
    //  Usage:
    //    std::string data = "abc";
    //    request.response_hex["foo"]["bar"] = data; // json: "616263", bt: "abc"
    //
    llarp::rpc::json_binary_proxy response_hex{response, llarp::rpc::json_binary_proxy::fmt::hex};

    //  Proxy Object:
    //  Encodes binary data as base_64 for json-encoded responses, leaves as binary for bt-encoded
    //  responses
    //
    //    Usage:
    //      std::string data = "abc"
    //      request.response_b64["foo"]["bar"] = data; json: "YWJj", bt: "abc"
    //
    llarp::rpc::json_binary_proxy response_b64{
        response, llarp::rpc::json_binary_proxy::fmt::base64};

    //  The oxenmq deferred send object into which the response will be sent when the `invoke`
    //  method returns.  If the response needs to happen later (i.e. not immediately after `invoke`
    //  returns) then you should call `defer()` to extract and clear this and then send the response
    //  via the returned DeferredSend object yourself.
    std::optional<oxenmq::Message::DeferredSend> replier;

    // Called to clear the current replier and return it.  After this call the automatic reply will
    // not be generated; the caller is responsible for calling `->reply` on the returned optional
    // itself.  This is typically used where a call has to be deferred, for example because it
    // depends on some network response to build the reply.
    oxenmq::Message::DeferredSend
    move()
    {
      auto r{std::move(*replier)};
      replier.reset();
      return r;
    }
  };

  //  Tag types that are inherited to set RPC endpoint properties

  //  RPC call wil take no input arguments
  //    Parameter dict can be passed, but will be ignored
  struct NoArgs : virtual RPCRequest
  {};

  // RPC call will be executed immediately
  struct Immediate : virtual RPCRequest
  {};

}  // namespace llarp::rpc
```


-------------------------------

Updated on 2023-02-01 at 20:39:33 +0000
