mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	msgpack-rpc: Allow selective deferral API calls
Since all API functions now run immediately after a msgpack-rpc request is parsed by libuv callbacks, a mechanism was added to override this behavior and allow certain functions to run in Nvim main loop. The mechanism is simple: Any API function tagged with the FUNC_ATTR_DEFERRED (a "dummy" attribute only used by msgpack-gen.lua) will be called when Nvim main loop receives a K_EVENT key. To implement this mechanism it was necessary some restructuration on the msgpack-rpc modules, especially in the msgpack-gen.lua script.
This commit is contained in:
		| @@ -34,6 +34,8 @@ c_params = Ct(c_void + c_param_list) | |||||||
| c_proto = Ct( | c_proto = Ct( | ||||||
|   Cg(c_type, 'return_type') * Cg(c_id, 'name') * |   Cg(c_type, 'return_type') * Cg(c_id, 'name') * | ||||||
|   fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * |   fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * | ||||||
|  |   Cg(Cc(false), 'deferred') * | ||||||
|  |   (fill * Cg((P('FUNC_ATTR_DEFERRED') * Cc(true)), 'deferred') ^ -1) * | ||||||
|   fill * P(';') |   fill * P(';') | ||||||
|   ) |   ) | ||||||
| grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) | grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) | ||||||
| @@ -159,9 +161,10 @@ for i = 1, #functions do | |||||||
|   local fn = functions[i] |   local fn = functions[i] | ||||||
|   local args = {} |   local args = {} | ||||||
|  |  | ||||||
|   output:write('static Object handle_'..fn.name..'(uint64_t channel_id, msgpack_object *req, Error *error)') |   output:write('static Object handle_'..fn.name..'(uint64_t channel_id, uint64_t request_id, Array args, Error *error)') | ||||||
|   output:write('\n{') |   output:write('\n{') | ||||||
|   output:write('\n  DLOG("Received msgpack-rpc call to '..fn.name..'(request id: %" PRIu64 ")", req->via.array.ptr[1].via.u64);') |   output:write('\n  DLOG("Handling msgpack-rpc call to '..fn.name..'(request id: %" PRIu64 ")", request_id);') | ||||||
|  |   output:write('\n  Object ret = NIL;') | ||||||
|   -- Declare/initialize variables that will hold converted arguments |   -- Declare/initialize variables that will hold converted arguments | ||||||
|   for j = 1, #fn.parameters do |   for j = 1, #fn.parameters do | ||||||
|     local param = fn.parameters[j] |     local param = fn.parameters[j] | ||||||
| @@ -169,8 +172,8 @@ for i = 1, #functions do | |||||||
|     output:write('\n  '..param[1]..' '..converted..' api_init_'..string.lower(real_type(param[1]))..';') |     output:write('\n  '..param[1]..' '..converted..' api_init_'..string.lower(real_type(param[1]))..';') | ||||||
|   end |   end | ||||||
|   output:write('\n') |   output:write('\n') | ||||||
|   output:write('\n  if (req->via.array.ptr[3].via.array.size != '..#fn.parameters..') {') |   output:write('\n  if (args.size != '..#fn.parameters..') {') | ||||||
|   output:write('\n    snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %u", req->via.array.ptr[3].via.array.size);') |   output:write('\n    snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') | ||||||
|   output:write('\n    error->set = true;') |   output:write('\n    error->set = true;') | ||||||
|   output:write('\n    goto cleanup;') |   output:write('\n    goto cleanup;') | ||||||
|   output:write('\n  }\n') |   output:write('\n  }\n') | ||||||
| @@ -179,14 +182,18 @@ for i = 1, #functions do | |||||||
|   for j = 1, #fn.parameters do |   for j = 1, #fn.parameters do | ||||||
|     local converted, convert_arg, param, arg |     local converted, convert_arg, param, arg | ||||||
|     param = fn.parameters[j] |     param = fn.parameters[j] | ||||||
|     arg = '(req->via.array.ptr[3].via.array.ptr + '..(j - 1)..')' |  | ||||||
|     converted = 'arg_'..j |     converted = 'arg_'..j | ||||||
|     convert_arg = 'msgpack_rpc_to_'..real_type(param[1]):lower() |     if real_type(param[1]) ~= 'Object' then | ||||||
|     output:write('\n  if (!'..convert_arg..'('..arg..', &'..converted..')) {') |       output:write('\n  if (args.items['..(j - 1)..'].type != kObjectType'..real_type(param[1])..') {') | ||||||
|       output:write('\n    snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') |       output:write('\n    snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') | ||||||
|       output:write('\n    error->set = true;') |       output:write('\n    error->set = true;') | ||||||
|       output:write('\n    goto cleanup;') |       output:write('\n    goto cleanup;') | ||||||
|     output:write('\n  }\n') |       output:write('\n  }') | ||||||
|  |       output:write('\n  '..converted..' = args.items['..(j - 1)..'].data.'..real_type(param[1]):lower()..';\n') | ||||||
|  |     else | ||||||
|  |       output:write('\n  '..converted..' = args.items['..(j - 1)..'];\n') | ||||||
|  |     end | ||||||
|  |  | ||||||
|     args[#args + 1] = converted |     args[#args + 1] = converted | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -228,7 +235,7 @@ for i = 1, #functions do | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   if fn.return_type ~= 'void' then |   if fn.return_type ~= 'void' then | ||||||
|     output:write('\n  Object ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') |     output:write('\n  ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') | ||||||
|   end |   end | ||||||
|   -- Now generate the cleanup label for freeing memory allocated for the |   -- Now generate the cleanup label for freeing memory allocated for the | ||||||
|   -- arguments |   -- arguments | ||||||
| @@ -238,20 +245,16 @@ for i = 1, #functions do | |||||||
|     local param = fn.parameters[j] |     local param = fn.parameters[j] | ||||||
|     output:write('\n  api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') |     output:write('\n  api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') | ||||||
|   end |   end | ||||||
|   if fn.return_type ~= 'void' then |  | ||||||
|   output:write('\n  return ret;\n}\n\n'); |   output:write('\n  return ret;\n}\n\n'); | ||||||
|   else |  | ||||||
|     output:write('\n  return NIL;\n}\n\n'); |  | ||||||
|   end |  | ||||||
| end | end | ||||||
|  |  | ||||||
| -- Generate a function that initializes method names with handler functions | -- Generate a function that initializes method names with handler functions | ||||||
| output:write([[ | output:write([[ | ||||||
| static Map(String, rpc_method_handler_fn) *methods = NULL; | static Map(String, MsgpackRpcRequestHandler) *methods = NULL; | ||||||
|  |  | ||||||
| void msgpack_rpc_init_method_table(void) | void msgpack_rpc_init_method_table(void) | ||||||
| { | { | ||||||
|   methods = map_new(String, rpc_method_handler_fn)(); |   methods = map_new(String, MsgpackRpcRequestHandler)(); | ||||||
|  |  | ||||||
| ]]) | ]]) | ||||||
|  |  | ||||||
| @@ -260,10 +263,11 @@ void msgpack_rpc_init_method_table(void) | |||||||
| local max_fname_len = 0 | local max_fname_len = 0 | ||||||
| for i = 1, #functions do | for i = 1, #functions do | ||||||
|   local fn = functions[i] |   local fn = functions[i] | ||||||
|   output:write('  map_put(String, rpc_method_handler_fn)(methods, '.. |   output:write('  map_put(String, MsgpackRpcRequestHandler)(methods, '.. | ||||||
|                '(String) {.data = "'..fn.name..'", '.. |                '(String) {.data = "'..fn.name..'", '.. | ||||||
|                '.size = sizeof("'..fn.name..'") - 1}, handle_'.. |                '.size = sizeof("'..fn.name..'") - 1}, '.. | ||||||
|                fn.name..');\n') |                '(MsgpackRpcRequestHandler) {.fn = handle_'..  fn.name.. | ||||||
|  |                ', .defer = '..tostring(fn.deferred)..'});\n') | ||||||
|  |  | ||||||
|   if #fn.name > max_fname_len then |   if #fn.name > max_fname_len then | ||||||
|     max_fname_len = #fn.name |     max_fname_len = #fn.name | ||||||
| @@ -273,26 +277,21 @@ end | |||||||
| output:write('\n}\n\n') | output:write('\n}\n\n') | ||||||
|  |  | ||||||
| output:write([[ | output:write([[ | ||||||
| Object msgpack_rpc_dispatch(uint64_t channel_id, | MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, | ||||||
|                             msgpack_object *req, |                                                      size_t name_len) | ||||||
|                             Error *error) |  | ||||||
| { | { | ||||||
|   msgpack_object method = req->via.array.ptr[2]; |   String m = { | ||||||
|   rpc_method_handler_fn handler = NULL; |     .data=(char *)name, | ||||||
|  |     .size=min(name_len, ]]..max_fname_len..[[) | ||||||
|  |   }; | ||||||
|  |   MsgpackRpcRequestHandler rv = | ||||||
|  |     map_get(String, MsgpackRpcRequestHandler)(methods, m); | ||||||
|  |  | ||||||
|   if (method.type == MSGPACK_OBJECT_BIN || method.type == MSGPACK_OBJECT_STR) { |   if (!rv.fn) { | ||||||
| ]]) |     rv.fn = msgpack_rpc_handle_missing_method; | ||||||
| output:write('    handler = map_get(String, rpc_method_handler_fn)') |  | ||||||
| output:write('(methods, (String){.data=(char *)method.via.bin.ptr,') |  | ||||||
| output:write('.size=min(method.via.bin.size, '..max_fname_len..')});\n') |  | ||||||
| output:write([[ |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (!handler) { |   return rv; | ||||||
|     handler = msgpack_rpc_handle_missing_method; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return handler(channel_id, req, error); |  | ||||||
| } | } | ||||||
| ]]) | ]]) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -179,6 +179,7 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef DEFINE_FUNC_ATTRIBUTES | #ifdef DEFINE_FUNC_ATTRIBUTES | ||||||
|  |   #define FUNC_ATTR_DEFERRED | ||||||
|   #define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC |   #define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC | ||||||
|   #define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x) |   #define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x) | ||||||
|   #define FUNC_ATTR_ALLOC_SIZE_PROD(x,y) REAL_FATTR_ALLOC_SIZE_PROD(x,y) |   #define FUNC_ATTR_ALLOC_SIZE_PROD(x,y) REAL_FATTR_ALLOC_SIZE_PROD(x,y) | ||||||
|   | |||||||
| @@ -108,4 +108,5 @@ MAP_IMPL(cstr_t, uint64_t, DEFAULT_INITIALIZER) | |||||||
| MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER) | MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER) | ||||||
| MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER) | MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER) | ||||||
| MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER) | MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER) | ||||||
| MAP_IMPL(String, rpc_method_handler_fn, DEFAULT_INITIALIZER) | #define MSGPACK_HANDLER_INITIALIZER {.fn = NULL, .defer = false} | ||||||
|  | MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER) | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ MAP_DECLS(cstr_t, uint64_t) | |||||||
| MAP_DECLS(cstr_t, ptr_t) | MAP_DECLS(cstr_t, ptr_t) | ||||||
| MAP_DECLS(ptr_t, ptr_t) | MAP_DECLS(ptr_t, ptr_t) | ||||||
| MAP_DECLS(uint64_t, ptr_t) | MAP_DECLS(uint64_t, ptr_t) | ||||||
| MAP_DECLS(String, rpc_method_handler_fn) | MAP_DECLS(String, MsgpackRpcRequestHandler) | ||||||
|  |  | ||||||
| #define map_new(T, U) map_##T##_##U##_new | #define map_new(T, U) map_##T##_##U##_new | ||||||
| #define map_free(T, U) map_##T##_##U##_free | #define map_free(T, U) map_##T##_##U##_free | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ | |||||||
| #include <uv.h> | #include <uv.h> | ||||||
| #include <msgpack.h> | #include <msgpack.h> | ||||||
|  |  | ||||||
|  | #include "nvim/lib/klist.h" | ||||||
|  |  | ||||||
| #include "nvim/api/private/helpers.h" | #include "nvim/api/private/helpers.h" | ||||||
| #include "nvim/api/vim.h" | #include "nvim/api/vim.h" | ||||||
| #include "nvim/msgpack_rpc/channel.h" | #include "nvim/msgpack_rpc/channel.h" | ||||||
| @@ -52,6 +54,17 @@ typedef struct { | |||||||
|   kvec_t(ChannelCallFrame *) call_stack; |   kvec_t(ChannelCallFrame *) call_stack; | ||||||
| } Channel; | } Channel; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |   Channel *channel; | ||||||
|  |   MsgpackRpcRequestHandler handler; | ||||||
|  |   Array args; | ||||||
|  |   uint64_t request_id; | ||||||
|  | } RequestEvent; | ||||||
|  |  | ||||||
|  | #define RequestEventFreer(x) | ||||||
|  | KMEMPOOL_INIT(RequestEventPool, RequestEvent, RequestEventFreer) | ||||||
|  | kmempool_t(RequestEventPool) *request_event_pool = NULL; | ||||||
|  |  | ||||||
| static uint64_t next_id = 1; | static uint64_t next_id = 1; | ||||||
| static PMap(uint64_t) *channels = NULL; | static PMap(uint64_t) *channels = NULL; | ||||||
| static PMap(cstr_t) *event_strings = NULL; | static PMap(cstr_t) *event_strings = NULL; | ||||||
| @@ -64,6 +77,7 @@ static msgpack_sbuffer out_buffer; | |||||||
| /// Initializes the module | /// Initializes the module | ||||||
| void channel_init(void) | void channel_init(void) | ||||||
| { | { | ||||||
|  |   request_event_pool = kmp_init(RequestEventPool); | ||||||
|   channels = pmap_new(uint64_t)(); |   channels = pmap_new(uint64_t)(); | ||||||
|   event_strings = pmap_new(cstr_t)(); |   event_strings = pmap_new(cstr_t)(); | ||||||
|   msgpack_sbuffer_init(&out_buffer); |   msgpack_sbuffer_init(&out_buffer); | ||||||
| @@ -352,12 +366,7 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof) | |||||||
|       goto end; |       goto end; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Perform the call |     handle_request(channel, &unpacked.data); | ||||||
|     WBuffer *resp = msgpack_rpc_call(channel->id, &unpacked.data, &out_buffer); |  | ||||||
|     // write the response |  | ||||||
|     if (!channel_write(channel, resp)) { |  | ||||||
|       goto end; |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (result == MSGPACK_UNPACK_NOMEM_ERROR) { |   if (result == MSGPACK_UNPACK_NOMEM_ERROR) { | ||||||
| @@ -387,6 +396,84 @@ end: | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void handle_request(Channel *channel, msgpack_object *request) | ||||||
|  |   FUNC_ATTR_NONNULL_ALL | ||||||
|  | { | ||||||
|  |   uint64_t request_id; | ||||||
|  |   Error error = ERROR_INIT; | ||||||
|  |   msgpack_rpc_validate(&request_id, request, &error); | ||||||
|  |  | ||||||
|  |   if (error.set) { | ||||||
|  |     // Validation failed, send response with error | ||||||
|  |     channel_write(channel, | ||||||
|  |                   serialize_response(request_id, &error, NIL, &out_buffer)); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Retrieve the request handler | ||||||
|  |   MsgpackRpcRequestHandler handler; | ||||||
|  |   msgpack_object method = request->via.array.ptr[2]; | ||||||
|  |  | ||||||
|  |   if (method.type == MSGPACK_OBJECT_BIN || method.type == MSGPACK_OBJECT_STR) { | ||||||
|  |     handler = msgpack_rpc_get_handler_for(method.via.bin.ptr, | ||||||
|  |                                           method.via.bin.size); | ||||||
|  |   } else { | ||||||
|  |     handler.fn = msgpack_rpc_handle_missing_method; | ||||||
|  |     handler.defer = false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Array args; | ||||||
|  |   msgpack_rpc_to_array(request->via.array.ptr + 3, &args); | ||||||
|  |  | ||||||
|  |   if (kv_size(channel->call_stack) || !handler.defer) { | ||||||
|  |     call_request_handler(channel, handler, args, request_id); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Defer calling the request handler. | ||||||
|  |   RequestEvent *event_data = kmp_alloc(RequestEventPool, request_event_pool); | ||||||
|  |   event_data->channel = channel; | ||||||
|  |   event_data->handler = handler; | ||||||
|  |   event_data->args = args; | ||||||
|  |   event_data->request_id = request_id; | ||||||
|  |   event_push((Event) { | ||||||
|  |     .handler = on_request_event, | ||||||
|  |     .data = event_data | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void on_request_event(Event event) | ||||||
|  | { | ||||||
|  |   RequestEvent *e = event.data; | ||||||
|  |   call_request_handler(e->channel, e->handler, e->args, e->request_id); | ||||||
|  |   kmp_free(RequestEventPool, request_event_pool, e); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void call_request_handler(Channel *channel, | ||||||
|  |                                  MsgpackRpcRequestHandler handler, | ||||||
|  |                                  Array args, | ||||||
|  |                                  uint64_t request_id) | ||||||
|  | { | ||||||
|  |   Error error = ERROR_INIT; | ||||||
|  |   Object result = handler.fn(channel->id, request_id, args, &error); | ||||||
|  |   // send the response | ||||||
|  |   msgpack_packer response; | ||||||
|  |   msgpack_packer_init(&response, &out_buffer, msgpack_sbuffer_write); | ||||||
|  |  | ||||||
|  |   if (error.set) { | ||||||
|  |     ELOG("Error dispatching msgpack-rpc call: %s(request: id %" PRIu64 ")", | ||||||
|  |          error.msg, | ||||||
|  |          request_id); | ||||||
|  |     channel_write(channel, | ||||||
|  |                   serialize_response(request_id, &error, NIL, &out_buffer)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   DLOG("Successfully completed mspgack-rpc call(request id: %" PRIu64 ")", | ||||||
|  |        request_id); | ||||||
|  |   channel_write(channel, | ||||||
|  |                 serialize_response(request_id, &error, result, &out_buffer)); | ||||||
|  | } | ||||||
|  |  | ||||||
| static bool channel_write(Channel *channel, WBuffer *buffer) | static bool channel_write(Channel *channel, WBuffer *buffer) | ||||||
| { | { | ||||||
|   bool success; |   bool success; | ||||||
|   | |||||||
| @@ -6,9 +6,15 @@ | |||||||
|  |  | ||||||
| /// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores | /// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores | ||||||
| /// functions of this type. | /// functions of this type. | ||||||
| typedef Object (*rpc_method_handler_fn)(uint64_t channel_id, | typedef struct { | ||||||
|                                         msgpack_object *req, |   Object (*fn)(uint64_t channel_id, | ||||||
|  |                uint64_t request_id, | ||||||
|  |                Array args, | ||||||
|                Error *error); |                Error *error); | ||||||
|  |   bool defer;  // Should the call be deferred to the main loop? This should | ||||||
|  |                // be true if the function mutates editor data structures such | ||||||
|  |                // as buffers, windows, tabs, or if it executes vimscript code. | ||||||
|  | } MsgpackRpcRequestHandler; | ||||||
|  |  | ||||||
| /// Initializes the msgpack-rpc method table | /// Initializes the msgpack-rpc method table | ||||||
| void msgpack_rpc_init_method_table(void); | void msgpack_rpc_init_method_table(void); | ||||||
| @@ -31,4 +37,7 @@ Object msgpack_rpc_dispatch(uint64_t channel_id, | |||||||
|                             Error *error) |                             Error *error) | ||||||
|   FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3); |   FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3); | ||||||
|  |  | ||||||
|  | MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, | ||||||
|  |                                                      size_t name_len) | ||||||
|  |   FUNC_ATTR_NONNULL_ARG(1); | ||||||
| #endif  // NVIM_MSGPACK_RPC_DEFS_H | #endif  // NVIM_MSGPACK_RPC_DEFS_H | ||||||
|   | |||||||
| @@ -140,10 +140,13 @@ bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg) | |||||||
|     case MSGPACK_OBJECT_EXT: |     case MSGPACK_OBJECT_EXT: | ||||||
|       switch (obj->via.ext.type) { |       switch (obj->via.ext.type) { | ||||||
|         case kObjectTypeBuffer: |         case kObjectTypeBuffer: | ||||||
|  |           arg->type = kObjectTypeBuffer; | ||||||
|           return msgpack_rpc_to_buffer(obj, &arg->data.buffer); |           return msgpack_rpc_to_buffer(obj, &arg->data.buffer); | ||||||
|         case kObjectTypeWindow: |         case kObjectTypeWindow: | ||||||
|  |           arg->type = kObjectTypeWindow; | ||||||
|           return msgpack_rpc_to_window(obj, &arg->data.window); |           return msgpack_rpc_to_window(obj, &arg->data.window); | ||||||
|         case kObjectTypeTabpage: |         case kObjectTypeTabpage: | ||||||
|  |           arg->type = kObjectTypeTabpage; | ||||||
|           return msgpack_rpc_to_tabpage(obj, &arg->data.tabpage); |           return msgpack_rpc_to_tabpage(obj, &arg->data.tabpage); | ||||||
|       } |       } | ||||||
|     default: |     default: | ||||||
| @@ -292,44 +295,6 @@ void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res) | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Validates the basic structure of the msgpack-rpc call and fills `res` |  | ||||||
| /// with the basic response structure. |  | ||||||
| /// |  | ||||||
| /// @param channel_id The channel id |  | ||||||
| /// @param req The parsed request object |  | ||||||
| /// @param res A packer that contains the response |  | ||||||
| WBuffer *msgpack_rpc_call(uint64_t channel_id, |  | ||||||
|                           msgpack_object *req, |  | ||||||
|                           msgpack_sbuffer *sbuffer) |  | ||||||
|   FUNC_ATTR_NONNULL_ARG(2) |  | ||||||
|   FUNC_ATTR_NONNULL_ARG(3) |  | ||||||
| { |  | ||||||
|   uint64_t response_id; |  | ||||||
|   Error error = ERROR_INIT; |  | ||||||
|   msgpack_rpc_validate(&response_id, req, &error); |  | ||||||
|  |  | ||||||
|   if (error.set) { |  | ||||||
|     return serialize_response(response_id, &error, NIL, sbuffer); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // dispatch the call |  | ||||||
|   Object rv = msgpack_rpc_dispatch(channel_id, req, &error); |  | ||||||
|   // send the response |  | ||||||
|   msgpack_packer response; |  | ||||||
|   msgpack_packer_init(&response, sbuffer, msgpack_sbuffer_write); |  | ||||||
|  |  | ||||||
|   if (error.set) { |  | ||||||
|     ELOG("Error dispatching msgpack-rpc call: %s(request: id %" PRIu64 ")", |  | ||||||
|          error.msg, |  | ||||||
|          response_id); |  | ||||||
|     return serialize_response(response_id, &error, NIL, sbuffer); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   DLOG("Successfully completed mspgack-rpc call(request id: %" PRIu64 ")", |  | ||||||
|        response_id); |  | ||||||
|   return serialize_response(response_id, &error, rv, sbuffer); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Finishes the msgpack-rpc call with an error message. | /// Finishes the msgpack-rpc call with an error message. | ||||||
| /// | /// | ||||||
| /// @param msg The error message | /// @param msg The error message | ||||||
| @@ -348,7 +313,8 @@ void msgpack_rpc_error(char *msg, msgpack_packer *res) | |||||||
|  |  | ||||||
| /// Handler executed when an invalid method name is passed | /// Handler executed when an invalid method name is passed | ||||||
| Object msgpack_rpc_handle_missing_method(uint64_t channel_id, | Object msgpack_rpc_handle_missing_method(uint64_t channel_id, | ||||||
|                                          msgpack_object *req, |                                          uint64_t request_id, | ||||||
|  |                                          Array args, | ||||||
|                                          Error *error) |                                          Error *error) | ||||||
| { | { | ||||||
|   snprintf(error->msg, sizeof(error->msg), "Invalid method name"); |   snprintf(error->msg, sizeof(error->msg), "Invalid method name"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Thiago de Arruda
					Thiago de Arruda