aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/msgpack_rpc/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/msgpack_rpc/channel.c')
-rw-r--r--src/nvim/msgpack_rpc/channel.c75
1 files changed, 45 insertions, 30 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 35549ce042..b671b8b545 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -5,8 +5,6 @@
#include <uv.h>
#include <msgpack.h>
-#include "nvim/lib/klist.h"
-
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/msgpack_rpc/channel.h"
@@ -69,10 +67,6 @@ typedef struct {
uint64_t request_id;
} RequestEvent;
-#define _noop(x)
-KMEMPOOL_INIT(RequestEventPool, RequestEvent, _noop)
-static kmempool_t(RequestEventPool) *request_event_pool = NULL;
-
static uint64_t next_id = 1;
static PMap(uint64_t) *channels = NULL;
static PMap(cstr_t) *event_strings = NULL;
@@ -85,7 +79,6 @@ static msgpack_sbuffer out_buffer;
/// Initializes the module
void channel_init(void)
{
- request_event_pool = kmp_init(RequestEventPool);
channels = pmap_new(uint64_t)();
event_strings = pmap_new(cstr_t)();
msgpack_sbuffer_init(&out_buffer);
@@ -232,7 +225,25 @@ Object channel_send_call(uint64_t id,
channel->pending_requests--;
if (frame.errored) {
- api_set_error(err, Exception, "%s", frame.result.data.string.data);
+ if (frame.result.type == kObjectTypeString) {
+ api_set_error(err, Exception, "%s", frame.result.data.string.data);
+ } else if (frame.result.type == kObjectTypeArray) {
+ // Should be an error in the form [type, message]
+ Array array = frame.result.data.array;
+ if (array.size == 2 && array.items[0].type == kObjectTypeInteger
+ && (array.items[0].data.integer == kErrorTypeException
+ || array.items[0].data.integer == kErrorTypeValidation)
+ && array.items[1].type == kObjectTypeString) {
+ err->type = (ErrorType) array.items[0].data.integer;
+ xstrlcpy(err->msg, array.items[1].data.string.data, sizeof(err->msg));
+ err->set = true;
+ } else {
+ api_set_error(err, Exception, "%s", "unknown error");
+ }
+ } else {
+ api_set_error(err, Exception, "%s", "unknown error");
+ }
+
api_free_object(frame.result);
}
@@ -442,20 +453,20 @@ static void handle_request(Channel *channel, msgpack_object *request)
// Retrieve the request handler
MsgpackRpcRequestHandler handler;
- msgpack_object method = request->via.array.ptr[2];
+ msgpack_object *method = msgpack_rpc_method(request);
- 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);
+ if (method) {
+ 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 = ARRAY_DICT_INIT;
- msgpack_rpc_to_array(request->via.array.ptr + 3, &args);
+ msgpack_rpc_to_array(msgpack_rpc_args(request), &args);
bool defer = (!kv_size(channel->call_stack) && handler.defer);
- RequestEvent *event_data = kmp_alloc(RequestEventPool, request_event_pool);
+ RequestEvent *event_data = xmalloc(sizeof(RequestEvent));
event_data->channel = channel;
event_data->handler = handler;
event_data->args = args;
@@ -476,18 +487,22 @@ static void on_request_event(Event event)
uint64_t request_id = e->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);
- channel_write(channel, serialize_response(channel->id,
- request_id,
- &error,
- result,
- &out_buffer));
+ if (request_id != NO_RESPONSE) {
+ // send the response
+ msgpack_packer response;
+ msgpack_packer_init(&response, &out_buffer, msgpack_sbuffer_write);
+ channel_write(channel, serialize_response(channel->id,
+ request_id,
+ &error,
+ result,
+ &out_buffer));
+ } else {
+ api_free_object(result);
+ }
// All arguments were freed already, but we still need to free the array
- free(args.items);
+ xfree(args.items);
decref(channel);
- kmp_free(RequestEventPool, request_event_pool, e);
+ xfree(e);
}
static bool channel_write(Channel *channel, WBuffer *buffer)
@@ -608,7 +623,7 @@ static void unsubscribe(Channel *channel, char *event)
// Since the string is no longer used by other channels, release it's memory
pmap_del(cstr_t)(event_strings, event_string);
- free(event_string);
+ xfree(event_string);
}
/// Close the channel streams/job and free the channel resources.
@@ -662,13 +677,13 @@ static void free_channel(Channel *channel)
pmap_free(cstr_t)(channel->subscribed_events);
kv_destroy(channel->call_stack);
kv_destroy(channel->delayed_notifications);
- free(channel);
+ xfree(channel);
}
static void close_cb(uv_handle_t *handle)
{
- free(handle->data);
- free(handle);
+ xfree(handle->data);
+ xfree(handle);
}
static Channel *register_channel(void)
@@ -745,7 +760,7 @@ static WBuffer *serialize_request(uint64_t channel_id,
WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size),
sbuffer->size,
refcount,
- free);
+ xfree);
msgpack_sbuffer_clear(sbuffer);
api_free_array(args);
return rv;
@@ -764,7 +779,7 @@ static WBuffer *serialize_response(uint64_t channel_id,
WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size),
sbuffer->size,
1, // responses only go though 1 channel
- free);
+ xfree);
msgpack_sbuffer_clear(sbuffer);
api_free_object(arg);
return rv;