Skip to content

Commit

Permalink
WIP: sockopen()
Browse files Browse the repository at this point in the history
  • Loading branch information
bfredl committed Apr 26, 2017
1 parent 7f6d3d3 commit 6e3795a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/nvim/eval.c
Expand Up @@ -14998,6 +14998,28 @@ static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
}

/// "sockopen()" function
static void f_sockopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_STRING) {
EMSG(_(e_invarg));
return;
}
if (argvars[2].v_type != VAR_DICT && argvars[2].v_type != VAR_UNKNOWN) {
// Wrong argument types
EMSG2(_(e_invarg2), "expected dictionary");
return;
}

const char *mode = tv_get_string(&argvars[0]);
const char *address = tv_get_string(&argvars[1]);

uint64_t id = channel_connect(address, 50);

rettv->vval.v_number = (varnumber_T)id;
rettv->v_type = VAR_NUMBER;
}

/// struct used in the array that's given to qsort()
typedef struct {
listitem_T *item;
Expand Down
1 change: 1 addition & 0 deletions src/nvim/eval.lua
Expand Up @@ -267,6 +267,7 @@ return {
simplify={args=1},
sin={args=1, func="float_op_wrapper", data="&sin"},
sinh={args=1, func="float_op_wrapper", data="&sinh"},
sockopen={args=3},
sort={args={1, 3}},
soundfold={args=1},
spellbadword={args={0, 1}},
Expand Down
25 changes: 25 additions & 0 deletions src/nvim/event/socket.c
Expand Up @@ -15,6 +15,7 @@
#include "nvim/vim.h"
#include "nvim/strings.h"
#include "nvim/path.h"
#include "nvim/main.h"
#include "nvim/memory.h"

#ifdef INCLUDE_GENERATED_DECLARATIONS
Expand Down Expand Up @@ -168,3 +169,27 @@ static void close_cb(uv_handle_t *handle)
watcher->close_cb(watcher, watcher->data);
}
}

static void connect_cb(uv_connect_t *req, int status)
{
int *ret_status = req->data;
*ret_status = status;
}

bool socket_connect(Loop *loop, Stream *stream, const char *address, int timeout)
{
uv_pipe_t *pipe = (uv_pipe_t *)&stream->uv.pipe;
int status = 1;
uv_connect_t req;
req.data = &status;
uv_pipe_init(&loop->uv, pipe, 0);
uv_pipe_connect(&req, pipe, address, connect_cb);
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, timeout, status != 1);
if (status == 0) {
stream_init(NULL, stream, -1, (uv_stream_t *)pipe);
return true;
} else {
// FIXME: leak
return false;
}
}
17 changes: 17 additions & 0 deletions src/nvim/msgpack_rpc/channel.c
Expand Up @@ -143,6 +143,23 @@ void channel_from_connection(SocketWatcher *watcher)
rstream_start(&channel->data.stream, parse_msgpack, channel);
}

uint64_t channel_connect(const char *address, int timeout)
{
Channel *channel = register_channel(kChannelTypeSocket, 0, NULL);
if (!socket_connect(&main_loop, &channel->data.stream, address, timeout)) {
decref(channel);
return 0;
}

incref(channel); // close channel only after the stream is closed
channel->data.stream.internal_close_cb = close_cb;
channel->data.stream.internal_data = channel;
wstream_init(&channel->data.stream, 0);
rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE);
rstream_start(&channel->data.stream, parse_msgpack, channel);
return channel->id;
}

/// Sends event/arguments to channel
///
/// @param id The channel id. If 0, the event will be sent to all
Expand Down

0 comments on commit 6e3795a

Please sign in to comment.