mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -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 <assert.h>
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
|
|
||||||
|
#include "nvim/map.h"
|
||||||
#include "nvim/log.h"
|
#include "nvim/log.h"
|
||||||
#include "nvim/os/msgpack_rpc.h"
|
#include "nvim/os/msgpack_rpc.h"
|
||||||
#include "nvim/os/msgpack_rpc_helpers.h"
|
#include "nvim/os/msgpack_rpc_helpers.h"
|
||||||
@ -241,12 +242,49 @@ for i = 1, #api.functions do
|
|||||||
end
|
end
|
||||||
output:write('\n};\n\n')
|
output:write('\n};\n\n')
|
||||||
|
|
||||||
|
-- Generate a function that initializes method names with handler functions
|
||||||
output:write([[
|
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,
|
Object msgpack_rpc_dispatch(uint64_t channel_id,
|
||||||
uint64_t method_id,
|
|
||||||
msgpack_object *req,
|
msgpack_object *req,
|
||||||
Error *error)
|
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 // method_id=0 is specially handled')
|
||||||
output:write('\n assert(method_id > 0);')
|
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);
|
return serialize_response(response_id, err, NIL, sbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t method_id = req->via.array.ptr[2].via.u64;
|
if (req->via.array.ptr[2].type == MSGPACK_OBJECT_POSITIVE_INTEGER
|
||||||
|
&& req->via.array.ptr[2].via.u64 == 0) {
|
||||||
if (method_id == 0) {
|
|
||||||
return serialize_metadata(response_id, channel_id, sbuffer);
|
return serialize_metadata(response_id, channel_id, sbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dispatch the call
|
// dispatch the call
|
||||||
Error error = { .set = false };
|
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
|
// send the response
|
||||||
msgpack_packer response;
|
msgpack_packer response;
|
||||||
msgpack_packer_init(&response, sbuffer, msgpack_sbuffer_write);
|
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";
|
return "Message type must be 0";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
|
if (req->via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER
|
||||||
return "Method id must be a 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) {
|
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,
|
msgpack_object *req,
|
||||||
Error *error);
|
Error *error);
|
||||||
|
|
||||||
|
|
||||||
|
/// Initializes the msgpack-rpc method table
|
||||||
|
void msgpack_rpc_init(void);
|
||||||
|
|
||||||
|
|
||||||
/// Dispatches to the actual API function after basic payload validation by
|
/// Dispatches to the actual API function after basic payload validation by
|
||||||
/// `msgpack_rpc_call`. It is responsible for validating/converting arguments
|
/// `msgpack_rpc_call`. It is responsible for validating/converting arguments
|
||||||
/// to C types, and converting the return value back to msgpack types.
|
/// 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
|
/// @param error Pointer to error structure
|
||||||
/// @return Some object
|
/// @return Some object
|
||||||
Object msgpack_rpc_dispatch(uint64_t channel_id,
|
Object msgpack_rpc_dispatch(uint64_t channel_id,
|
||||||
uint64_t method_id,
|
|
||||||
msgpack_object *req,
|
msgpack_object *req,
|
||||||
Error *error)
|
Error *error)
|
||||||
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3);
|
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3);
|
||||||
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "os/msgpack_rpc.h.generated.h"
|
# include "os/msgpack_rpc.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#include "nvim/os/shell.h"
|
#include "nvim/os/shell.h"
|
||||||
#include "nvim/os/signal.h"
|
#include "nvim/os/signal.h"
|
||||||
#include "nvim/os/job.h"
|
#include "nvim/os/job.h"
|
||||||
|
#include "nvim/os/msgpack_rpc.h"
|
||||||
|
|
||||||
#if defined(HAVE_SYS_IOCTL_H)
|
#if defined(HAVE_SYS_IOCTL_H)
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
@ -164,6 +165,7 @@ void mch_init(void)
|
|||||||
mac_conv_init();
|
mac_conv_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
msgpack_rpc_init();
|
||||||
event_init();
|
event_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user