peer: make connect command an async command.

So it can return failure.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2016-01-22 06:41:48 +10:30
parent 366f8a5f3f
commit d8959b3117

View file

@ -15,6 +15,12 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
struct json_connecting {
/* This owns us, so we're freed after command_fail or command_success */
struct command *cmd;
const char *name, *port;
};
/* Send and receive (encrypted) hello message. */ /* Send and receive (encrypted) hello message. */
static struct io_plan *peer_test_check(struct io_conn *conn, struct peer *peer) static struct io_plan *peer_test_check(struct io_conn *conn, struct peer *peer)
{ {
@ -82,15 +88,24 @@ static struct peer *new_peer(struct lightningd_state *state,
static struct io_plan *peer_connected_out(struct io_conn *conn, static struct io_plan *peer_connected_out(struct io_conn *conn,
struct lightningd_state *state, struct lightningd_state *state,
char *dest) struct json_connecting *connect)
{ {
struct json_result *response;
struct peer *peer = new_peer(state, conn, SOCK_STREAM, IPPROTO_TCP, struct peer *peer = new_peer(state, conn, SOCK_STREAM, IPPROTO_TCP,
"out"); "out");
if (!peer) { if (!peer) {
log_unusual(peer->log, "Failed to make peer for %s", dest); command_fail(connect->cmd, "Failed to make peer for %s:%s",
connect->name, connect->port);
return io_close(conn); return io_close(conn);
} }
log_info(peer->log, "Connected out to %s", dest); log_info(peer->log, "Connected out to %s:%s",
connect->name, connect->port);
response = new_json_result(connect);
json_object_start(response, NULL);
json_object_end(response);
command_success(connect->cmd, response);
return peer_crypto_setup(conn, peer, peer_test); return peer_crypto_setup(conn, peer, peer_test);
} }
@ -190,19 +205,19 @@ void setup_listeners(struct lightningd_state *state, unsigned int portnum)
fatal("Could not bind to a network address"); fatal("Could not bind to a network address");
} }
static void peer_failed(struct lightningd_state *state, char *dest) static void peer_failed(struct lightningd_state *state,
struct json_connecting *connect)
{ {
/* FIXME: Better diagnostics! */ /* FIXME: Better diagnostics! */
log_unusual(state->base_log, "Connect to %s failed", dest); command_fail(connect->cmd, "Failed to connect to peer %s:%s",
connect->name, connect->port);
} }
static void json_connect(struct command *cmd, static void json_connect(struct command *cmd,
const char *buffer, const jsmntok_t *params) const char *buffer, const jsmntok_t *params)
{ {
struct json_result *response; struct json_connecting *connect;
jsmntok_t *host, *port; jsmntok_t *host, *port;
const char *hoststr, *portstr;
char *dest;
json_get_params(buffer, params, "host", &host, "port", &port, NULL); json_get_params(buffer, params, "host", &host, "port", &port, NULL);
@ -211,26 +226,22 @@ static void json_connect(struct command *cmd,
return; return;
} }
hoststr = tal_strndup(cmd->state, buffer + host->start, connect = tal(cmd, struct json_connecting);
connect->cmd = cmd;
connect->name = tal_strndup(connect, buffer + host->start,
host->end - host->start); host->end - host->start);
portstr = tal_strndup(cmd->state, buffer + port->start, connect->port = tal_strndup(connect, buffer + port->start,
port->end - port->start); port->end - port->start);
dest = tal_fmt(cmd->state, "%s:%s", hoststr, portstr); if (!dns_resolve_and_connect(cmd->state, connect->name, connect->port,
if (!dns_resolve_and_connect(cmd->state, hoststr, portstr, peer_connected_out, peer_failed, connect)) {
peer_connected_out, peer_failed, dest)) {
command_fail(cmd, "DNS failed"); command_fail(cmd, "DNS failed");
return; return;
} }
response = new_json_result(cmd);
json_object_start(response, NULL);
json_object_end(response);
command_success(cmd, response);
} }
const struct json_command connect_command = { const struct json_command connect_command = {
"connect", "connect",
json_connect, json_connect,
"Connect to a {host} at {port}", "Connect to a {host} at {port}",
"Returns an empty result (meaning connection in progress)" "Returns an empty result on success"
}; };