aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/msgpack_rpc
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /src/nvim/msgpack_rpc
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-aucmd_textputpost.tar.gz
rneovim-aucmd_textputpost.tar.bz2
rneovim-aucmd_textputpost.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'src/nvim/msgpack_rpc')
-rw-r--r--src/nvim/msgpack_rpc/channel.c263
-rw-r--r--src/nvim/msgpack_rpc/channel.h17
-rw-r--r--src/nvim/msgpack_rpc/channel_defs.h21
-rw-r--r--src/nvim/msgpack_rpc/helpers.c22
-rw-r--r--src/nvim/msgpack_rpc/helpers.h5
-rw-r--r--src/nvim/msgpack_rpc/server.c13
-rw-r--r--src/nvim/msgpack_rpc/server.h6
-rw-r--r--src/nvim/msgpack_rpc/unpacker.c118
-rw-r--r--src/nvim/msgpack_rpc/unpacker.h9
9 files changed, 247 insertions, 227 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index d60e18590f..0fb1ebf931 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
#include <assert.h>
#include <inttypes.h>
#include <msgpack/object.h>
@@ -10,7 +7,6 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
-#include <uv.h>
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
@@ -24,9 +20,11 @@
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
+#include "nvim/func_attr.h"
+#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
-#include "nvim/map.h"
+#include "nvim/map_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
@@ -35,16 +33,82 @@
#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/os/input.h"
#include "nvim/rbuffer.h"
-#include "nvim/types.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_client.h"
-#if MIN_LOG_LEVEL > LOGLVL_DBG
+#ifdef NVIM_LOG_DEBUG
+# define REQ "[request] "
+# define RES "[response] "
+# define NOT "[notify] "
+# define ERR "[error] "
+
+// Cannot define array with negative offsets, so this one is needed to be added
+// to MSGPACK_UNPACK_\* values.
+# define MUR_OFF 2
+
+static const char *const msgpack_error_messages[] = {
+ [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found",
+ [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string",
+ [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error",
+ [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory",
+};
+
+static void log_close(FILE *f)
+{
+ fputc('\n', f);
+ fflush(f);
+ fclose(f);
+ log_unlock();
+}
+
+static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed)
+{
+ msgpack_unpacked unpacked;
+ msgpack_unpacked_init(&unpacked);
+ DLOGN("RPC ->ch %" PRIu64 ": ", channel_id);
+ const msgpack_unpack_return result =
+ msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL);
+ switch (result) {
+ case MSGPACK_UNPACK_SUCCESS: {
+ uint64_t type = unpacked.data.via.array.ptr[0].via.u64;
+ log_lock();
+ FILE *f = open_log_file();
+ fprintf(f, type ? (type == 1 ? RES : NOT) : REQ);
+ msgpack_object_print(f, unpacked.data);
+ log_close(f);
+ msgpack_unpacked_destroy(&unpacked);
+ break;
+ }
+ case MSGPACK_UNPACK_EXTRA_BYTES:
+ case MSGPACK_UNPACK_CONTINUE:
+ case MSGPACK_UNPACK_PARSE_ERROR:
+ case MSGPACK_UNPACK_NOMEM_ERROR: {
+ log_lock();
+ FILE *f = open_log_file();
+ fprintf(f, ERR);
+ fprintf(f, "%s", msgpack_error_messages[result + MUR_OFF]);
+ log_close(f);
+ break;
+ }
+ }
+}
+
+static void log_client_msg(uint64_t channel_id, bool is_request, const char *name)
+{
+ DLOGN("RPC <-ch %" PRIu64 ": ", channel_id);
+ log_lock();
+ FILE *f = open_log_file();
+ fprintf(f, "%s: %s", is_request ? REQ : RES, name);
+ log_close(f);
+}
+
+#else
# define log_client_msg(...)
# define log_server_msg(...)
#endif
-static PMap(cstr_t) event_strings = MAP_INIT;
+static Set(cstr_t) event_strings = SET_INIT;
static msgpack_sbuffer out_buffer;
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -71,7 +135,7 @@ void rpc_start(Channel *channel)
if (channel->streamtype != kChannelStreamInternal) {
Stream *out = channel_outstream(channel);
-#if MIN_LOG_LEVEL <= LOGLVL_DBG
+#ifdef NVIM_LOG_DEBUG
Stream *in = channel_instream(channel);
DLOG("rpc ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id,
(void *)in, (void *)out);
@@ -141,9 +205,15 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem
// Push the frame
ChannelCallFrame frame = { request_id, false, false, NIL, NULL };
kv_push(rpc->call_stack, &frame);
- LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned);
+ LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned || rpc->closed);
(void)kv_pop(rpc->call_stack);
+ if (rpc->closed) {
+ api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id);
+ channel_decref(channel);
+ return NIL;
+ }
+
if (frame.errored) {
if (frame.result.type == kObjectTypeString) {
api_set_error(err, kErrorTypeException, "%s",
@@ -188,14 +258,12 @@ void rpc_subscribe(uint64_t id, char *event)
abort();
}
- char *event_string = pmap_get(cstr_t)(&event_strings, event);
-
- if (!event_string) {
- event_string = xstrdup(event);
- pmap_put(cstr_t)(&event_strings, event_string, event_string);
+ const char **key_alloc = NULL;
+ if (set_put_ref(cstr_t, &event_strings, event, &key_alloc)) {
+ *key_alloc = xstrdup(event);
}
- pmap_put(cstr_t)(channel->rpc.subscribed_events, event_string, event_string);
+ set_put(cstr_t, channel->rpc.subscribed_events, *key_alloc);
}
/// Unsubscribes to event broadcasts
@@ -242,26 +310,43 @@ end:
channel_decref(channel);
}
+static ChannelCallFrame *find_call_frame(RpcState *rpc, uint32_t request_id)
+{
+ for (size_t i = 0; i < kv_size(rpc->call_stack); i++) {
+ ChannelCallFrame *frame = kv_Z(rpc->call_stack, i);
+ if (frame->request_id == request_id) {
+ return frame;
+ }
+ }
+ return NULL;
+}
+
static void parse_msgpack(Channel *channel)
{
Unpacker *p = channel->rpc.unpacker;
while (unpacker_advance(p)) {
if (p->type == kMessageTypeRedrawEvent) {
- if (p->grid_line_event) {
- ui_client_event_raw_line(p->grid_line_event);
- } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) {
- p->ui_handler.fn(p->result.data.array);
+ // When exiting, ui_client_stop() has already been called, so don't handle UI events.
+ if (ui_client_channel_id && !exiting) {
+ if (p->grid_line_event) {
+ ui_client_event_raw_line(p->grid_line_event);
+ } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) {
+ p->ui_handler.fn(p->result.data.array);
+ }
}
arena_mem_free(arena_finish(&p->arena));
} else if (p->type == kMessageTypeResponse) {
- ChannelCallFrame *frame = kv_last(channel->rpc.call_stack);
- if (p->request_id != frame->request_id) {
+ ChannelCallFrame *frame = channel->rpc.client_type == kClientTypeMsgpackRpc
+ ? find_call_frame(&channel->rpc, p->request_id)
+ : kv_last(channel->rpc.call_stack);
+ if (frame == NULL || p->request_id != frame->request_id) {
char buf[256];
snprintf(buf, sizeof(buf),
- "ch %" PRIu64 " returned a response with an unknown request "
- "id. Ensure the client is properly synchronized",
- channel->id);
+ "ch %" PRIu64 " (type=%" PRIu32 ") returned a response with an unknown request "
+ "id %" PRIu32 ". Ensure the client is properly synchronized",
+ channel->id, (unsigned)channel->rpc.client_type, p->request_id);
chan_close_with_error(channel, buf, LOGLVL_ERR);
+ return;
}
frame->returned = true;
frame->errored = (p->error.type != kObjectTypeNil);
@@ -486,7 +571,7 @@ static void broadcast_event(const char *name, Array args)
map_foreach_value(&channels, channel, {
if (channel->is_rpc
- && pmap_has(cstr_t)(channel->rpc.subscribed_events, name)) {
+ && set_has(cstr_t, channel->rpc.subscribed_events, name)) {
kv_push(subscribed, channel);
}
});
@@ -514,24 +599,12 @@ end:
static void unsubscribe(Channel *channel, char *event)
{
- char *event_string = pmap_get(cstr_t)(&event_strings, event);
- if (!event_string) {
+ if (!set_has(cstr_t, &event_strings, event)) {
WLOG("RPC: ch %" PRIu64 ": tried to unsubscribe unknown event '%s'",
channel->id, event);
return;
}
- pmap_del(cstr_t)(channel->rpc.subscribed_events, event_string);
-
- map_foreach_value(&channels, channel, {
- if (channel->is_rpc
- && pmap_has(cstr_t)(channel->rpc.subscribed_events, event_string)) {
- return;
- }
- });
-
- // Since the string is no longer used by other channels, release it's memory
- pmap_del(cstr_t)(&event_strings, event_string);
- xfree(event_string);
+ set_del(cstr_t, channel->rpc.subscribed_events, event);
}
/// Mark rpc state as closed, and release its reference to the channel.
@@ -547,6 +620,10 @@ void rpc_close(Channel *channel)
if (channel->streamtype == kChannelStreamStdio
|| (channel->id == ui_client_channel_id && channel->streamtype != kChannelStreamProc)) {
+ if (channel->streamtype == kChannelStreamStdio) {
+ // Avoid hanging when there are no other UIs and a prompt is triggered on exit.
+ remote_ui_disconnect(channel->id);
+ }
exit_from_channel(0);
}
}
@@ -557,13 +634,7 @@ void rpc_free(Channel *channel)
unpacker_teardown(channel->rpc.unpacker);
xfree(channel->rpc.unpacker);
- // Unsubscribe from all events
- char *event_string;
- map_foreach_value(channel->rpc.subscribed_events, event_string, {
- unsubscribe(channel, event_string);
- });
-
- pmap_destroy(cstr_t)(channel->rpc.subscribed_events);
+ set_destroy(cstr_t, channel->rpc.subscribed_events);
kv_destroy(channel->rpc.call_stack);
api_free_dictionary(channel->rpc.info);
}
@@ -575,7 +646,7 @@ static void chan_close_with_error(Channel *channel, char *msg, int loglevel)
ChannelCallFrame *frame = kv_A(channel->rpc.call_stack, i);
frame->returned = true;
frame->errored = true;
- frame->result = STRING_OBJ(cstr_to_string(msg));
+ frame->result = CSTR_TO_OBJ(msg);
}
channel_close(channel->id, kChannelPartRpc, NULL);
@@ -612,7 +683,7 @@ static WBuffer *serialize_response(uint64_t channel_id, MsgpackRpcRequestHandler
} else {
Array args = ARRAY_DICT_INIT;
ADD(args, INTEGER_OBJ(err->type));
- ADD(args, STRING_OBJ(cstr_to_string(err->msg)));
+ ADD(args, CSTR_TO_OBJ(err->msg));
msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"),
args, &pac);
api_free_array(args);
@@ -638,6 +709,25 @@ void rpc_set_client_info(uint64_t id, Dictionary info)
api_free_dictionary(chan->rpc.info);
chan->rpc.info = info;
+
+ // Parse "type" on "info" and set "client_type"
+ const char *type = get_client_info(chan, "type");
+ if (type == NULL || strequal(type, "remote")) {
+ chan->rpc.client_type = kClientTypeRemote;
+ } else if (strequal(type, "msgpack-rpc")) {
+ chan->rpc.client_type = kClientTypeMsgpackRpc;
+ } else if (strequal(type, "ui")) {
+ chan->rpc.client_type = kClientTypeUi;
+ } else if (strequal(type, "embedder")) {
+ chan->rpc.client_type = kClientTypeEmbedder;
+ } else if (strequal(type, "host")) {
+ chan->rpc.client_type = kClientTypeHost;
+ } else if (strequal(type, "plugin")) {
+ chan->rpc.client_type = kClientTypePlugin;
+ } else {
+ chan->rpc.client_type = kClientTypeUnknown;
+ }
+
channel_info_changed(chan, false);
}
@@ -646,14 +736,15 @@ Dictionary rpc_client_info(Channel *chan)
return copy_dictionary(chan->rpc.info, NULL);
}
-const char *rpc_client_name(Channel *chan)
+const char *get_client_info(Channel *chan, const char *key)
+ FUNC_ATTR_NONNULL_ALL
{
if (!chan->is_rpc) {
return NULL;
}
Dictionary info = chan->rpc.info;
for (size_t i = 0; i < info.size; i++) {
- if (strequal("name", info.items[i].key.data)
+ if (strequal(key, info.items[i].key.data)
&& info.items[i].value.type == kObjectTypeString) {
return info.items[i].value.data.string.data;
}
@@ -662,69 +753,11 @@ const char *rpc_client_name(Channel *chan)
return NULL;
}
-#if MIN_LOG_LEVEL <= LOGLVL_DBG
-# define REQ "[request] "
-# define RES "[response] "
-# define NOT "[notify] "
-# define ERR "[error] "
-
-// Cannot define array with negative offsets, so this one is needed to be added
-// to MSGPACK_UNPACK_\* values.
-# define MUR_OFF 2
-
-static const char *const msgpack_error_messages[] = {
- [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found",
- [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string",
- [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error",
- [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory",
-};
-
-static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed)
-{
- msgpack_unpacked unpacked;
- msgpack_unpacked_init(&unpacked);
- DLOGN("RPC ->ch %" PRIu64 ": ", channel_id);
- const msgpack_unpack_return result =
- msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL);
- switch (result) {
- case MSGPACK_UNPACK_SUCCESS: {
- uint64_t type = unpacked.data.via.array.ptr[0].via.u64;
- log_lock();
- FILE *f = open_log_file();
- fprintf(f, type ? (type == 1 ? RES : NOT) : REQ);
- msgpack_object_print(f, unpacked.data);
- log_close(f);
- msgpack_unpacked_destroy(&unpacked);
- break;
- }
- case MSGPACK_UNPACK_EXTRA_BYTES:
- case MSGPACK_UNPACK_CONTINUE:
- case MSGPACK_UNPACK_PARSE_ERROR:
- case MSGPACK_UNPACK_NOMEM_ERROR: {
- log_lock();
- FILE *f = open_log_file();
- fprintf(f, ERR);
- fprintf(f, "%s", msgpack_error_messages[result + MUR_OFF]);
- log_close(f);
- break;
- }
- }
-}
-
-static void log_client_msg(uint64_t channel_id, bool is_request, const char *name)
+void rpc_free_all_mem(void)
{
- DLOGN("RPC <-ch %" PRIu64 ": ", channel_id);
- log_lock();
- FILE *f = open_log_file();
- fprintf(f, "%s: %s", is_request ? REQ : RES, name);
- log_close(f);
-}
-
-static void log_close(FILE *f)
-{
- fputc('\n', f);
- fflush(f);
- fclose(f);
- log_unlock();
+ cstr_t key;
+ set_foreach(&event_strings, key, {
+ xfree((void *)key);
+ });
+ set_destroy(cstr_t, &event_strings);
}
-#endif
diff --git a/src/nvim/msgpack_rpc/channel.h b/src/nvim/msgpack_rpc/channel.h
index ce5806930c..818bee8318 100644
--- a/src/nvim/msgpack_rpc/channel.h
+++ b/src/nvim/msgpack_rpc/channel.h
@@ -1,25 +1,24 @@
-#ifndef NVIM_MSGPACK_RPC_CHANNEL_H
-#define NVIM_MSGPACK_RPC_CHANNEL_H
+#pragma once
-#include <stdbool.h>
-#include <uv.h>
+#include <stdint.h> // IWYU pragma: keep
-#include "nvim/api/private/defs.h"
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/channel.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/socket.h"
-#include "nvim/macros.h"
-#include "nvim/vim.h"
+#include "nvim/event/wstream.h"
+#include "nvim/macros_defs.h"
+#include "nvim/memory_defs.h" // IWYU pragma: keep
+#include "nvim/msgpack_rpc/channel_defs.h" // IWYU pragma: export
#define METHOD_MAXLEN 512
/// HACK: os/input.c drains this queue immediately before blocking for input.
/// Events on this queue are async-safe, but they need the resolved state
/// of os_inchar(), so they are processed "just-in-time".
-EXTERN MultiQueue *ch_before_blocking_events INIT(= NULL);
+EXTERN MultiQueue *ch_before_blocking_events INIT( = NULL);
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/channel.h.generated.h"
#endif
-#endif // NVIM_MSGPACK_RPC_CHANNEL_H
diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h
index 404e68329a..20b8a89afb 100644
--- a/src/nvim/msgpack_rpc/channel_defs.h
+++ b/src/nvim/msgpack_rpc/channel_defs.h
@@ -1,19 +1,29 @@
-#ifndef NVIM_MSGPACK_RPC_CHANNEL_DEFS_H
-#define NVIM_MSGPACK_RPC_CHANNEL_DEFS_H
+#pragma once
#include <msgpack.h>
#include <stdbool.h>
#include <uv.h>
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/event/process.h"
#include "nvim/event/socket.h"
-#include "nvim/vim.h"
+#include "nvim/map_defs.h"
typedef struct Channel Channel;
typedef struct Unpacker Unpacker;
+typedef enum {
+ kClientTypeUnknown = -1,
+ kClientTypeRemote = 0,
+ kClientTypeMsgpackRpc = 5,
+ kClientTypeUi = 1,
+ kClientTypeEmbedder = 2,
+ kClientTypeHost = 3,
+ kClientTypePlugin = 4,
+} ClientType;
+
typedef struct {
uint32_t request_id;
bool returned, errored;
@@ -31,12 +41,11 @@ typedef struct {
} RequestEvent;
typedef struct {
- PMap(cstr_t) subscribed_events[1];
+ Set(cstr_t) subscribed_events[1];
bool closed;
Unpacker *unpacker;
uint32_t next_request_id;
kvec_t(ChannelCallFrame *) call_stack;
Dictionary info;
+ ClientType client_type;
} RpcState;
-
-#endif // NVIM_MSGPACK_RPC_CHANNEL_DEFS_H
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index 5f0f03dd69..1fdfc9e536 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
#include <msgpack/object.h>
#include <msgpack/sbuffer.h>
#include <msgpack/unpack.h>
@@ -12,14 +9,13 @@
#include "klib/kvec.h"
#include "msgpack/pack.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/assert.h"
-#include "nvim/event/wstream.h"
+#include "nvim/assert_defs.h"
+#include "nvim/func_attr.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/types.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "keysets.generated.h" // IWYU pragma: export
# include "msgpack_rpc/helpers.c.generated.h"
#endif
@@ -84,12 +80,8 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
*cur.aobj = INTEGER_OBJ((Integer)cur.mobj->via.u64);
}
break;
-#ifdef NVIM_MSGPACK_HAS_FLOAT32
case MSGPACK_OBJECT_FLOAT32:
case MSGPACK_OBJECT_FLOAT64:
-#else
- case MSGPACK_OBJECT_FLOAT:
-#endif
{
STATIC_ASSERT(sizeof(Float) == sizeof(cur.mobj->via.f64),
"Msgpack floating-point size does not match API integer");
@@ -156,12 +148,8 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
case MSGPACK_OBJECT_BOOLEAN:
case MSGPACK_OBJECT_POSITIVE_INTEGER:
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
-#ifdef NVIM_MSGPACK_HAS_FLOAT32
case MSGPACK_OBJECT_FLOAT32:
case MSGPACK_OBJECT_FLOAT64:
-#else
- case MSGPACK_OBJECT_FLOAT:
-#endif
case MSGPACK_OBJECT_EXT:
case MSGPACK_OBJECT_MAP:
case MSGPACK_OBJECT_ARRAY:
@@ -484,8 +472,8 @@ msgpack_object *msgpack_rpc_method(msgpack_object *req)
{
msgpack_object *obj = req->via.array.ptr
+ (msgpack_rpc_is_notification(req) ? 1 : 2);
- return obj->type == MSGPACK_OBJECT_STR || obj->type == MSGPACK_OBJECT_BIN ?
- obj : NULL;
+ return obj->type == MSGPACK_OBJECT_STR || obj->type == MSGPACK_OBJECT_BIN
+ ? obj : NULL;
}
msgpack_object *msgpack_rpc_args(msgpack_object *req)
diff --git a/src/nvim/msgpack_rpc/helpers.h b/src/nvim/msgpack_rpc/helpers.h
index dab8a16b6b..dd2096f305 100644
--- a/src/nvim/msgpack_rpc/helpers.h
+++ b/src/nvim/msgpack_rpc/helpers.h
@@ -1,5 +1,4 @@
-#ifndef NVIM_MSGPACK_RPC_HELPERS_H
-#define NVIM_MSGPACK_RPC_HELPERS_H
+#pragma once
#include <msgpack.h>
#include <stdbool.h>
@@ -19,5 +18,3 @@
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/helpers.h.generated.h"
#endif
-
-#endif // NVIM_MSGPACK_RPC_HELPERS_H
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index 1d75c208be..f3627eaa61 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
@@ -10,6 +7,7 @@
#include "nvim/channel.h"
#include "nvim/eval.h"
#include "nvim/event/socket.h"
+#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/log.h"
#include "nvim/main.h"
@@ -71,8 +69,8 @@ static void close_socket_watcher(SocketWatcher **watcher)
static void set_vservername(garray_T *srvs)
{
char *default_server = (srvs->ga_len > 0)
- ? ((SocketWatcher **)srvs->ga_data)[0]->addr
- : NULL;
+ ? ((SocketWatcher **)srvs->ga_data)[0]->addr
+ : NULL;
set_vim_var_string(VV_SEND_SERVER, default_server, -1);
}
@@ -91,13 +89,14 @@ char *server_address_new(const char *name)
{
static uint32_t count = 0;
char fmt[ADDRESS_MAX_SIZE];
+ const char *appname = get_appname();
#ifdef MSWIN
int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
- name ? name : "nvim", os_get_pid(), count++);
+ name ? name : appname, os_get_pid(), count++);
#else
char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32,
- dir, name ? name : "nvim", os_get_pid(), count++);
+ dir, name ? name : appname, os_get_pid(), count++);
xfree(dir);
#endif
if ((size_t)r >= sizeof(fmt)) {
diff --git a/src/nvim/msgpack_rpc/server.h b/src/nvim/msgpack_rpc/server.h
index 5446e40e0b..71b578a14b 100644
--- a/src/nvim/msgpack_rpc/server.h
+++ b/src/nvim/msgpack_rpc/server.h
@@ -1,9 +1,7 @@
-#ifndef NVIM_MSGPACK_RPC_SERVER_H
-#define NVIM_MSGPACK_RPC_SERVER_H
+#pragma once
-#include <stdio.h>
+#include <stddef.h> // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/server.h.generated.h"
#endif
-#endif // NVIM_MSGPACK_RPC_SERVER_H
diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c
index 44a16beb48..38263381bf 100644
--- a/src/nvim/msgpack_rpc/unpacker.c
+++ b/src/nvim/msgpack_rpc/unpacker.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -8,8 +5,9 @@
#include "klib/kvec.h"
#include "mpack/conv.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/ascii.h"
-#include "nvim/macros.h"
+#include "nvim/ascii_defs.h"
+#include "nvim/grid.h"
+#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/helpers.h"
@@ -87,7 +85,7 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
*result = NIL;
break;
case MPACK_TOKEN_BOOLEAN:
- *result = BOOL(mpack_unpack_boolean(node->tok));
+ *result = BOOLEAN_OBJ(mpack_unpack_boolean(node->tok));
break;
case MPACK_TOKEN_SINT:
*result = INTEGER_OBJ(mpack_unpack_sint(node->tok));
@@ -172,14 +170,12 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
node->data[0].p = result;
break;
}
-
- default:
- abort();
}
}
static void api_parse_exit(mpack_parser_t *parser, mpack_node_t *node)
-{}
+{
+}
void unpacker_init(Unpacker *p)
{
@@ -292,13 +288,13 @@ error:
// objects. For the moment "redraw/grid_line" uses a hand-rolled decoder,
// to avoid a blizzard of small objects for each screen cell.
//
-// <0>[2, "redraw", <10>[{11}["method", <12>[args], <12>[args], ...], <11>[...], ...]]
+// <0>[2, "redraw", <10>[<11>["method", <12>[args], <12>[args], ...], <11>[...], ...]]
//
// Where [args] gets unpacked as an Array. Note: first {11} is not saved as a state.
//
// When method is "grid_line", we furthermore decode a cell at a time like:
//
-// <0>[2, "redraw", <10>[{11}["grid_line", <14>[g, r, c, [<15>[cell], <15>[cell], ...]], ...], <11>[...], ...]]
+// <0>[2, "redraw", <10>[<11>["grid_line", <14>[g, r, c, [<15>[cell], <15>[cell], ...], <16>wrap]], <11>[...], ...]]
//
// where [cell] is [char, repeat, attr], where 'repeat' and 'attr' is optional
@@ -323,7 +319,7 @@ bool unpacker_advance(Unpacker *p)
return false;
}
- if (p->state == 15) {
+ if (p->state == 16) {
// grid_line event already unpacked
goto done;
} else {
@@ -358,10 +354,10 @@ done:
p->state = 0;
return true;
case 13:
- case 15:
+ case 16:
p->ncalls--;
if (p->ncalls > 0) {
- p->state = (p->state == 15) ? 14 : 12;
+ p->state = (p->state == 16) ? 14 : 12;
} else if (p->nevents > 0) {
p->state = 11;
} else {
@@ -382,7 +378,6 @@ bool unpacker_parse_redraw(Unpacker *p)
size_t size = p->read_size;
GridLineEvent *g = p->grid_line_event;
-// -V:NEXT_TYPE:501
#define NEXT_TYPE(tok, typ) \
result = mpack_rtoken(&data, &size, &tok); \
if (result == MPACK_EOF) { \
@@ -394,7 +389,6 @@ bool unpacker_parse_redraw(Unpacker *p)
return false; \
}
-redo:
switch (p->state) {
case 10:
NEXT_TYPE(tok, MPACK_TOKEN_ARRAY);
@@ -440,7 +434,7 @@ redo:
case 14:
NEXT_TYPE(tok, MPACK_TOKEN_ARRAY);
int eventarrsize = (int)tok.length;
- if (eventarrsize != 4) {
+ if (eventarrsize != 5) {
p->state = -1;
return false;
}
@@ -462,58 +456,64 @@ redo:
FALLTHROUGH;
case 15:
- assert(g->icell < g->ncells);
-
- NEXT_TYPE(tok, MPACK_TOKEN_ARRAY);
- int cellarrsize = (int)tok.length;
- if (cellarrsize < 1 || cellarrsize > 3) {
- p->state = -1;
- return false;
- }
+ for (; g->icell != g->ncells; g->icell++) {
+ assert(g->icell < g->ncells);
+
+ NEXT_TYPE(tok, MPACK_TOKEN_ARRAY);
+ int cellarrsize = (int)tok.length;
+ if (cellarrsize < 1 || cellarrsize > 3) {
+ p->state = -1;
+ return false;
+ }
- NEXT_TYPE(tok, MPACK_TOKEN_STR);
- if (tok.length > size) {
- return false;
- }
+ NEXT_TYPE(tok, MPACK_TOKEN_STR);
+ if (tok.length > size) {
+ return false;
+ }
- const char *cellbuf = data;
- size_t cellsize = tok.length;
- data += cellsize;
- size -= cellsize;
+ const char *cellbuf = data;
+ size_t cellsize = tok.length;
+ data += cellsize;
+ size -= cellsize;
- if (cellarrsize >= 2) {
- NEXT_TYPE(tok, MPACK_TOKEN_SINT);
- g->cur_attr = (int)tok.data.value.lo;
- }
+ if (cellarrsize >= 2) {
+ NEXT_TYPE(tok, MPACK_TOKEN_SINT);
+ g->cur_attr = (int)tok.data.value.lo;
+ }
- int repeat = 1;
- if (cellarrsize >= 3) {
- NEXT_TYPE(tok, MPACK_TOKEN_UINT);
- repeat = (int)tok.data.value.lo;
- }
+ int repeat = 1;
+ if (cellarrsize >= 3) {
+ NEXT_TYPE(tok, MPACK_TOKEN_UINT);
+ repeat = (int)tok.data.value.lo;
+ }
- g->clear_width = 0;
- if (g->icell == g->ncells - 1 && cellsize == 1 && cellbuf[0] == ' ' && repeat > 1) {
- g->clear_width = repeat;
- } else {
- for (int r = 0; r < repeat; r++) {
- if (g->coloff >= (int)grid_line_buf_size) {
- p->state = -1;
- return false;
+ g->clear_width = 0;
+ if (g->icell == g->ncells - 1 && cellsize == 1 && cellbuf[0] == ' ' && repeat > 1) {
+ g->clear_width = repeat;
+ } else {
+ schar_T sc = schar_from_buf(cellbuf, cellsize);
+ for (int r = 0; r < repeat; r++) {
+ if (g->coloff >= (int)grid_line_buf_size) {
+ p->state = -1;
+ return false;
+ }
+ grid_line_buf_char[g->coloff] = sc;
+ grid_line_buf_attr[g->coloff++] = g->cur_attr;
}
- memcpy(grid_line_buf_char[g->coloff], cellbuf, cellsize);
- grid_line_buf_char[g->coloff][cellsize] = NUL;
- grid_line_buf_attr[g->coloff++] = g->cur_attr;
}
+
+ p->read_ptr = data;
+ p->read_size = size;
}
+ p->state = 16;
+ FALLTHROUGH;
- g->icell++;
+ case 16:
+ NEXT_TYPE(tok, MPACK_TOKEN_BOOLEAN);
+ g->wrap = mpack_unpack_boolean(tok);
p->read_ptr = data;
p->read_size = size;
- if (g->icell == g->ncells) {
- return true;
- }
- goto redo;
+ return true;
case 12:
return true;
diff --git a/src/nvim/msgpack_rpc/unpacker.h b/src/nvim/msgpack_rpc/unpacker.h
index b8b2d38d3b..53af29761e 100644
--- a/src/nvim/msgpack_rpc/unpacker.h
+++ b/src/nvim/msgpack_rpc/unpacker.h
@@ -1,5 +1,4 @@
-#ifndef NVIM_MSGPACK_RPC_UNPACKER_H
-#define NVIM_MSGPACK_RPC_UNPACKER_H
+#pragma once
#include <inttypes.h>
#include <stdbool.h>
@@ -11,9 +10,9 @@
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/grid_defs.h"
-#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/msgpack_rpc/channel_defs.h"
-#include "nvim/types.h"
+#include "nvim/types_defs.h"
#include "nvim/ui_client.h"
struct Unpacker {
@@ -49,5 +48,3 @@ struct Unpacker {
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/unpacker.h.generated.h"
#endif
-
-#endif // NVIM_MSGPACK_RPC_UNPACKER_H