mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 05:05:00 -07:00
msgpack-rpc: Accept method names in requests
This commit is contained in:
parent
9d5e2c34c9
commit
aa23d2f835
@ -91,6 +91,7 @@ output:write([[
|
||||
#include <assert.h>
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/map.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/os/msgpack_rpc.h"
|
||||
#include "nvim/os/msgpack_rpc_helpers.h"
|
||||
@ -241,12 +242,49 @@ for i = 1, #api.functions do
|
||||
end
|
||||
output:write('\n};\n\n')
|
||||
|
||||
-- Generate a function that initializes method names with handler functions
|
||||
output:write([[
|
||||
static Map(cstr_t, uint64_t) *rpc_method_ids = NULL;
|
||||
|
||||
void msgpack_rpc_init(void)
|
||||
{
|
||||
rpc_method_ids = map_new(cstr_t, uint64_t)();
|
||||
|
||||
]])
|
||||
|
||||
-- Msgpack strings must be copied to a 0-terminated temporary buffer before
|
||||
-- searching in the map, so we keep track of the maximum method name length in
|
||||
-- order to create the smallest possible buffer for xstrlcpy
|
||||
local max_fname_len = 0
|
||||
for i = 1, #api.functions do
|
||||
local fn = api.functions[i]
|
||||
output:write(' map_put(cstr_t, uint64_t)(rpc_method_ids, "'
|
||||
..fn.name..'", '..i..');\n')
|
||||
if #fn.name > max_fname_len then
|
||||
max_fname_len = #fn.name
|
||||
end
|
||||
end
|
||||
|
||||
output:write('\n}\n\n')
|
||||
|
||||
output:write([[
|
||||
#define min(X, Y) (X < Y ? X : Y)
|
||||
|
||||
Object msgpack_rpc_dispatch(uint64_t channel_id,
|
||||
uint64_t method_id,
|
||||
msgpack_object *req,
|
||||
Error *error)
|
||||
{
|
||||
msgpack_object method = req->via.array.ptr[2];
|
||||
uint64_t method_id = method.via.u64;
|
||||
|
||||
if (method.type == MSGPACK_OBJECT_RAW) {
|
||||
char method_name[]]..(max_fname_len + 1)..[[];
|
||||
xstrlcpy(method_name, method.via.raw.ptr, min(method.via.raw.size, ]] ..(max_fname_len)..[[) + 1);
|
||||
method_id = map_get(cstr_t, uint64_t)(rpc_method_ids, method_name);
|
||||
if (!method_id) {
|
||||
method_id = UINT64_MAX;
|
||||
}
|
||||
}
|
||||
]])
|
||||
output:write('\n // method_id=0 is specially handled')
|
||||
output:write('\n assert(method_id > 0);')
|
||||
|
@ -39,15 +39,14 @@ WBuffer *msgpack_rpc_call(uint64_t channel_id,
|
||||
return serialize_response(response_id, err, NIL, sbuffer);
|
||||
}
|
||||
|
||||
uint64_t method_id = req->via.array.ptr[2].via.u64;
|
||||
|
||||
if (method_id == 0) {
|
||||
if (req->via.array.ptr[2].type == MSGPACK_OBJECT_POSITIVE_INTEGER
|
||||
&& req->via.array.ptr[2].via.u64 == 0) {
|
||||
return serialize_metadata(response_id, channel_id, sbuffer);
|
||||
}
|
||||
|
||||
// dispatch the call
|
||||
Error error = { .set = false };
|
||||
Object rv = msgpack_rpc_dispatch(channel_id, method_id, req, &error);
|
||||
Object rv = msgpack_rpc_dispatch(channel_id, req, &error);
|
||||
// send the response
|
||||
msgpack_packer response;
|
||||
msgpack_packer_init(&response, sbuffer, msgpack_sbuffer_write);
|
||||
@ -235,8 +234,9 @@ static char *msgpack_rpc_validate(uint64_t *response_id, msgpack_object *req)
|
||||
return "Message type must be 0";
|
||||
}
|
||||
|
||||
if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
|
||||
return "Method id must be a positive integer";
|
||||
if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER
|
||||
&& req->via.array.ptr[2].type != MSGPACK_OBJECT_RAW) {
|
||||
return "Method must be a positive integer or a string";
|
||||
}
|
||||
|
||||
if (req->via.array.ptr[3].type != MSGPACK_OBJECT_ARRAY) {
|
||||
|
@ -21,6 +21,11 @@ typedef Object (*rpc_method_handler_fn)(uint64_t channel_id,
|
||||
msgpack_object *req,
|
||||
Error *error);
|
||||
|
||||
|
||||
/// Initializes the msgpack-rpc method table
|
||||
void msgpack_rpc_init(void);
|
||||
|
||||
|
||||
/// Dispatches to the actual API function after basic payload validation by
|
||||
/// `msgpack_rpc_call`. It is responsible for validating/converting arguments
|
||||
/// to C types, and converting the return value back to msgpack types.
|
||||
@ -33,11 +38,11 @@ typedef Object (*rpc_method_handler_fn)(uint64_t channel_id,
|
||||
/// @param error Pointer to error structure
|
||||
/// @return Some object
|
||||
Object msgpack_rpc_dispatch(uint64_t channel_id,
|
||||
uint64_t method_id,
|
||||
msgpack_object *req,
|
||||
Error *error)
|
||||
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3);
|
||||
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/msgpack_rpc.h.generated.h"
|
||||
#endif
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nvim/os/shell.h"
|
||||
#include "nvim/os/signal.h"
|
||||
#include "nvim/os/job.h"
|
||||
#include "nvim/os/msgpack_rpc.h"
|
||||
|
||||
#if defined(HAVE_SYS_IOCTL_H)
|
||||
# include <sys/ioctl.h>
|
||||
@ -164,6 +165,7 @@ void mch_init(void)
|
||||
mac_conv_init();
|
||||
#endif
|
||||
|
||||
msgpack_rpc_init();
|
||||
event_init();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user