# RPC Protocol ## JSON-RPC 2.0 The server implements **JSON-RPC 2.0** over TCP with length-prefixed framing (see [Architecture → Wire framing](architecture.md#wire-framing)). Batch requests are not supported — only single request objects are processed. ### Request format ```json { "jsonrpc": "2.0", "method": "", "params": {}, "id": } ``` The `params` field is accepted but currently ignored by all implemented methods. The `id` field is required; requests without it receive a `-32600 Invalid Request` error. ### Success response ```json { "jsonrpc": "2.0", "result": , "id": } ``` ### Error response ```json { "jsonrpc": "2.0", "error": { "code": , "message": "" }, "id": } ``` ### Error codes | Code | Meaning | When | |---|---|---| | `-32700` | Parse error | Request is not valid JSON | | `-32600` | Invalid Request | Missing `jsonrpc`, `method`, or `id` fields, or `jsonrpc != "2.0"` | | `-32601` | Method not found | No handler registered for the requested method name | | `-32000` | Server error | Handler threw an exception | > **Known issue**: Non-object JSON (arrays, strings, numbers, null) causes a `nlohmann::json::type_error` instead of a clean `-32600` response. See `tests/test_rpc_edge_cases.cpp`. Source: `src/rpc_server.cpp` — `RpcServer::process()` and `create_error()`. ## Methods ### `get-intrinsic-params` Retrieves intrinsic camera parameters as a flat 3×3 matrix (row-major, 9 doubles). **Request:** ```json {"jsonrpc": "2.0", "method": "get-intrinsic-params", "id": 1} ``` **Response:** ```json {"jsonrpc": "2.0", "result": , "id": 1} ``` Result type: `vector` (size 9), Base64-encoded. ### `get-extrinsic-params` Retrieves extrinsic camera parameters as a flat 4×4 matrix (row-major, 16 doubles). **Request:** ```json {"jsonrpc": "2.0", "method": "get-extrinsic-params", "id": 2} ``` **Response:** ```json {"jsonrpc": "2.0", "result": , "id": 2} ``` Result type: `vector` (size 16), Base64-encoded. ### `get-cloud-point` Retrieves the current field-of-view point cloud. **Request:** ```json {"jsonrpc": "2.0", "method": "get-cloud-point", "id": 3} ``` **Response:** ```json {"jsonrpc": "2.0", "result": {"width": int, "height": int, "data": }, "id": 3} ``` Result type: `matrix WxH` (list of `[x, y, z]` points), Base64-encoded. > **Note**: The standalone mock server (`server_main.cpp`) returns these as raw JSON arrays (not Base64-encoded) via `Service`. The Base64 encoding is expected to be implemented on the Unity side per `API.md`. ## Handler registration Handlers are registered with `RpcServer::register_method()`. Two forms exist: ### C++ handler ```cpp rpc_server.register_method("get-intrinsic-params", [&](const json& params) { return service.get_intrinsic_params(); // returns vector }); ``` The handler returns `std::variant`. If a `json` is returned, it is placed directly in the `result` field. If a `std::string` is returned, it is placed as-is. ### C callback handler ```cpp rpc_string* my_callback(rpc_string* params_json) { // params_json->s contains the JSON params as a string // return a result string (JSON or raw) return crpc_str_create("result_data", 11); } rpc_server.register_method("my-method", my_callback); ``` The C callback receives the JSON `params` as a string in `rpc_string->s`. The return value's string is parsed as JSON if possible; otherwise it is used as a raw string in the `result` field. Source: `src/rpc_server.cpp` — `register_method(name, callback_t)` overload. ## Base64 encoding `include/cloud_point_rpc/rpc_coder.hpp`, `src/rpc_coder.cpp` - `Base64RPCCoder` implements the `IRPCCoder` interface with `encode()` and `decode()` methods. - Uses the [aklomp/base64](https://github.com/aklomp/base64) library (Meson wrap `subprojects/aklomp-base64.wrap`). - `encode(vector) → string` and `decode(string) → vector`. - Includes overflow protection: throws `std::length_error` if input exceeds safe size limits. > Per `API.md`, Base64 encoding/decoding of camera data is expected to be done on the **Unity side**. The `Base64RPCCoder` class is available for C++ consumers but is not used by the mock server's response path. ## Client-side usage `include/cloud_point_rpc/rpc_client.hpp` `RpcClient` wraps `jsonrpccxx::JsonRpcClient` and provides typed access: ```cpp score::TCPConnector connector(ip, port); score::RpcClient client(connector); auto intrinsic = client.get_intrinsic_params(); // vector auto extrinsic = client.get_extrinsic_params(); // vector auto cloud = client.get_cloud_point(); // vector> ``` The interactive CLI (`src/cli.cpp`) and `minimal_client` (`src/minimal_client.cpp`) demonstrate client usage.