mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
lightningd/connect_control: routines to control connecting (move from peer_control.c)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
4cf274b1c0
commit
a83ff83328
@ -51,6 +51,7 @@ LIGHTNINGD_SRC := \
|
||||
lightningd/build_utxos.c \
|
||||
lightningd/chaintopology.c \
|
||||
lightningd/channel.c \
|
||||
lightningd/connect_control.c \
|
||||
lightningd/gossip_control.c \
|
||||
lightningd/gossip_msg.c \
|
||||
lightningd/hsm_control.c \
|
||||
|
194
lightningd/connect_control.c
Normal file
194
lightningd/connect_control.c
Normal file
@ -0,0 +1,194 @@
|
||||
#include <bitcoin/pubkey.h>
|
||||
#include <ccan/list/list.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/wireaddr.h>
|
||||
#include <gossipd/gen_gossip_wire.h>
|
||||
#include <lightningd/connect_control.h>
|
||||
#include <lightningd/jsonrpc.h>
|
||||
#include <lightningd/lightningd.h>
|
||||
#include <lightningd/log.h>
|
||||
#include <lightningd/subd.h>
|
||||
|
||||
struct connect {
|
||||
struct list_node list;
|
||||
struct pubkey id;
|
||||
struct command *cmd;
|
||||
};
|
||||
|
||||
static void destroy_connect(struct connect *c)
|
||||
{
|
||||
list_del(&c->list);
|
||||
}
|
||||
|
||||
static struct connect *new_connect(struct lightningd *ld,
|
||||
const struct pubkey *id,
|
||||
struct command *cmd)
|
||||
{
|
||||
struct connect *c = tal(cmd, struct connect);
|
||||
c->id = *id;
|
||||
c->cmd = cmd;
|
||||
list_add(&ld->connects, &c->list);
|
||||
tal_add_destructor(c, destroy_connect);
|
||||
return c;
|
||||
}
|
||||
|
||||
void connect_succeeded(struct lightningd *ld, const struct pubkey *id)
|
||||
{
|
||||
struct connect *i, *next;
|
||||
|
||||
/* Careful! Completing command frees connect. */
|
||||
list_for_each_safe(&ld->connects, i, next, list) {
|
||||
struct json_result *response;
|
||||
|
||||
if (!pubkey_eq(&i->id, id))
|
||||
continue;
|
||||
|
||||
response = new_json_result(i->cmd);
|
||||
json_object_start(response, NULL);
|
||||
json_add_pubkey(response, "id", id);
|
||||
json_object_end(response);
|
||||
command_success(i->cmd, response);
|
||||
}
|
||||
}
|
||||
|
||||
void connect_failed(struct lightningd *ld, const struct pubkey *id,
|
||||
const char *error)
|
||||
{
|
||||
struct connect *i, *next;
|
||||
|
||||
/* Careful! Completing command frees connect. */
|
||||
list_for_each_safe(&ld->connects, i, next, list) {
|
||||
if (pubkey_eq(&i->id, id))
|
||||
command_fail(i->cmd, "%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
void peer_connection_failed(struct lightningd *ld, const u8 *msg)
|
||||
{
|
||||
struct pubkey id;
|
||||
u32 attempts, timediff;
|
||||
bool addr_unknown;
|
||||
char *error;
|
||||
|
||||
if (!fromwire_gossip_peer_connection_failed(msg, NULL, &id, &timediff,
|
||||
&attempts, &addr_unknown))
|
||||
fatal(
|
||||
"Gossip gave bad GOSSIP_PEER_CONNECTION_FAILED message %s",
|
||||
tal_hex(msg, msg));
|
||||
|
||||
if (addr_unknown) {
|
||||
error = tal_fmt(
|
||||
msg, "No address known for node %s, please provide one",
|
||||
type_to_string(msg, struct pubkey, &id));
|
||||
} else {
|
||||
error = tal_fmt(msg, "Could not connect to %s after %d seconds and %d attempts",
|
||||
type_to_string(msg, struct pubkey, &id), timediff,
|
||||
attempts);
|
||||
}
|
||||
|
||||
connect_failed(ld, &id, error);
|
||||
}
|
||||
|
||||
static void json_connect(struct command *cmd,
|
||||
const char *buffer, const jsmntok_t *params)
|
||||
{
|
||||
jsmntok_t *hosttok, *porttok, *idtok;
|
||||
struct pubkey id;
|
||||
char *id_str;
|
||||
char *atptr;
|
||||
char *ataddr = NULL;
|
||||
int atidx;
|
||||
const char *name;
|
||||
struct wireaddr addr;
|
||||
u8 *msg;
|
||||
|
||||
if (!json_get_params(cmd, buffer, params,
|
||||
"id", &idtok,
|
||||
"?host", &hosttok,
|
||||
"?port", &porttok,
|
||||
NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for id@addrport form */
|
||||
id_str = tal_strndup(cmd, buffer + idtok->start,
|
||||
idtok->end - idtok->start);
|
||||
atptr = strchr(id_str, '@');
|
||||
if (atptr) {
|
||||
atidx = atptr - id_str;
|
||||
ataddr = tal_strdup(cmd, atptr + 1);
|
||||
/* Cut id. */
|
||||
idtok->end = idtok->start + atidx;
|
||||
}
|
||||
|
||||
if (!json_tok_pubkey(buffer, idtok, &id)) {
|
||||
command_fail(cmd, "id %.*s not valid",
|
||||
idtok->end - idtok->start,
|
||||
buffer + idtok->start);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hosttok && ataddr) {
|
||||
command_fail(cmd,
|
||||
"Can't specify host as both xxx@yyy "
|
||||
"and separate argument");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get parseable host if provided somehow */
|
||||
if (hosttok)
|
||||
name = tal_strndup(cmd, buffer + hosttok->start,
|
||||
hosttok->end - hosttok->start);
|
||||
else if (ataddr)
|
||||
name = ataddr;
|
||||
else
|
||||
name = NULL;
|
||||
|
||||
/* Port without host name? */
|
||||
if (porttok && !name) {
|
||||
command_fail(cmd, "Can't specify port without host");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Was there parseable host name? */
|
||||
if (name) {
|
||||
/* Is there a port? */
|
||||
if (porttok) {
|
||||
u32 port;
|
||||
if (!json_tok_number(buffer, porttok, &port)) {
|
||||
command_fail(cmd, "Port %.*s not valid",
|
||||
porttok->end - porttok->start,
|
||||
buffer + porttok->start);
|
||||
return;
|
||||
}
|
||||
addr.port = port;
|
||||
} else {
|
||||
addr.port = DEFAULT_PORT;
|
||||
}
|
||||
if (!parse_wireaddr(name, &addr, addr.port) || !addr.port) {
|
||||
command_fail(cmd, "Host %s:%u not valid",
|
||||
name, addr.port);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tell it about the address. */
|
||||
msg = towire_gossipctl_peer_addrhint(cmd, &id, &addr);
|
||||
subd_send_msg(cmd->ld->gossip, take(msg));
|
||||
}
|
||||
|
||||
/* Now tell it to try reaching it. */
|
||||
msg = towire_gossipctl_reach_peer(cmd, &id);
|
||||
subd_send_msg(cmd->ld->gossip, take(msg));
|
||||
|
||||
/* Leave this here for gossip_peer_connected */
|
||||
new_connect(cmd->ld, &id, cmd);
|
||||
command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static const struct json_command connect_command = {
|
||||
"connect",
|
||||
json_connect,
|
||||
"Connect to {id} at {host} (which can end in ':port' if not default). "
|
||||
"{id} can also be of the form id@host"
|
||||
};
|
||||
AUTODATA(json_command, &connect_command);
|
15
lightningd/connect_control.h
Normal file
15
lightningd/connect_control.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef LIGHTNING_LIGHTNINGD_CONNECT_CONTROL_H
|
||||
#define LIGHTNING_LIGHTNINGD_CONNECT_CONTROL_H
|
||||
#include "config.h"
|
||||
|
||||
struct lightningd;
|
||||
struct pubkey;
|
||||
|
||||
void connect_succeeded(struct lightningd *ld, const struct pubkey *id);
|
||||
void connect_failed(struct lightningd *ld, const struct pubkey *id,
|
||||
const char *error);
|
||||
|
||||
/* Gossipd was unable to connect to the peer */
|
||||
void peer_connection_failed(struct lightningd *ld, const u8 *msg);
|
||||
|
||||
#endif /* LIGHTNING_LIGHTNINGD_CONNECT_CONTROL_H */
|
@ -17,6 +17,7 @@
|
||||
#include <hsmd/capabilities.h>
|
||||
#include <hsmd/gen_hsm_client_wire.h>
|
||||
#include <inttypes.h>
|
||||
#include <lightningd/connect_control.h>
|
||||
#include <lightningd/gossip_msg.h>
|
||||
#include <lightningd/hsm_control.h>
|
||||
#include <lightningd/jsonrpc.h>
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <lightningd/bitcoind.h>
|
||||
#include <lightningd/build_utxos.h>
|
||||
#include <lightningd/chaintopology.h>
|
||||
#include <lightningd/connect_control.h>
|
||||
#include <lightningd/hsm_control.h>
|
||||
#include <lightningd/jsonrpc.h>
|
||||
#include <lightningd/log.h>
|
||||
@ -45,12 +46,6 @@
|
||||
#include <wire/peer_wire.h>
|
||||
#include <wire/wire_sync.h>
|
||||
|
||||
struct connect {
|
||||
struct list_node list;
|
||||
struct pubkey id;
|
||||
struct command *cmd;
|
||||
};
|
||||
|
||||
/* FIXME: Reorder */
|
||||
static void copy_to_parent_log(const char *prefix,
|
||||
enum log_level level,
|
||||
@ -167,54 +162,6 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel)
|
||||
remove_sig(channel->last_tx);
|
||||
}
|
||||
|
||||
static void destroy_connect(struct connect *c)
|
||||
{
|
||||
list_del(&c->list);
|
||||
}
|
||||
|
||||
static struct connect *new_connect(struct lightningd *ld,
|
||||
const struct pubkey *id,
|
||||
struct command *cmd)
|
||||
{
|
||||
struct connect *c = tal(cmd, struct connect);
|
||||
c->id = *id;
|
||||
c->cmd = cmd;
|
||||
list_add(&ld->connects, &c->list);
|
||||
tal_add_destructor(c, destroy_connect);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void connect_succeeded(struct lightningd *ld, const struct pubkey *id)
|
||||
{
|
||||
struct connect *i, *next;
|
||||
|
||||
/* Careful! Completing command frees connect. */
|
||||
list_for_each_safe(&ld->connects, i, next, list) {
|
||||
struct json_result *response;
|
||||
|
||||
if (!pubkey_eq(&i->id, id))
|
||||
continue;
|
||||
|
||||
response = new_json_result(i->cmd);
|
||||
json_object_start(response, NULL);
|
||||
json_add_pubkey(response, "id", id);
|
||||
json_object_end(response);
|
||||
command_success(i->cmd, response);
|
||||
}
|
||||
}
|
||||
|
||||
static void connect_failed(struct lightningd *ld, const struct pubkey *id,
|
||||
const char *error)
|
||||
{
|
||||
struct connect *i, *next;
|
||||
|
||||
/* Careful! Completing command frees connect. */
|
||||
list_for_each_safe(&ld->connects, i, next, list) {
|
||||
if (pubkey_eq(&i->id, id))
|
||||
command_fail(i->cmd, "%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
static void channel_errmsg(struct channel *channel,
|
||||
int peer_fd, int gossip_fd,
|
||||
const struct crypto_state *cs,
|
||||
@ -413,39 +360,6 @@ void peer_already_connected(struct lightningd *ld, const u8 *msg)
|
||||
connect_succeeded(ld, &id);
|
||||
}
|
||||
|
||||
void peer_connection_failed(struct lightningd *ld, const u8 *msg)
|
||||
{
|
||||
struct pubkey id;
|
||||
u32 attempts, timediff;
|
||||
struct connect *i, *next;
|
||||
bool addr_unknown;
|
||||
char *error;
|
||||
|
||||
if (!fromwire_gossip_peer_connection_failed(msg, NULL, &id, &timediff,
|
||||
&attempts, &addr_unknown))
|
||||
fatal(
|
||||
"Gossip gave bad GOSSIP_PEER_CONNECTION_FAILED message %s",
|
||||
tal_hex(msg, msg));
|
||||
|
||||
if (addr_unknown) {
|
||||
error = tal_fmt(
|
||||
msg, "No address known for node %s, please provide one",
|
||||
type_to_string(msg, struct pubkey, &id));
|
||||
} else {
|
||||
error = tal_fmt(msg, "Could not connect to %s after %d seconds and %d attempts",
|
||||
type_to_string(msg, struct pubkey, &id), timediff,
|
||||
attempts);
|
||||
}
|
||||
|
||||
/* Careful! Completing command frees connect. */
|
||||
list_for_each_safe(&ld->connects, i, next, list) {
|
||||
if (!pubkey_eq(&i->id, &id))
|
||||
continue;
|
||||
|
||||
command_fail(i->cmd, "%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
static struct channel *channel_by_channel_id(struct peer *peer,
|
||||
const struct channel_id *channel_id)
|
||||
{
|
||||
@ -549,110 +463,6 @@ struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void json_connect(struct command *cmd,
|
||||
const char *buffer, const jsmntok_t *params)
|
||||
{
|
||||
jsmntok_t *hosttok, *porttok, *idtok;
|
||||
struct pubkey id;
|
||||
char *id_str;
|
||||
char *atptr;
|
||||
char *ataddr = NULL;
|
||||
int atidx;
|
||||
const char *name;
|
||||
struct wireaddr addr;
|
||||
u8 *msg;
|
||||
|
||||
if (!json_get_params(cmd, buffer, params,
|
||||
"id", &idtok,
|
||||
"?host", &hosttok,
|
||||
"?port", &porttok,
|
||||
NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for id@addrport form */
|
||||
id_str = tal_strndup(cmd, buffer + idtok->start,
|
||||
idtok->end - idtok->start);
|
||||
atptr = strchr(id_str, '@');
|
||||
if (atptr) {
|
||||
atidx = atptr - id_str;
|
||||
ataddr = tal_strdup(cmd, atptr + 1);
|
||||
/* Cut id. */
|
||||
idtok->end = idtok->start + atidx;
|
||||
}
|
||||
|
||||
if (!json_tok_pubkey(buffer, idtok, &id)) {
|
||||
command_fail(cmd, "id %.*s not valid",
|
||||
idtok->end - idtok->start,
|
||||
buffer + idtok->start);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hosttok && ataddr) {
|
||||
command_fail(cmd,
|
||||
"Can't specify host as both xxx@yyy "
|
||||
"and separate argument");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get parseable host if provided somehow */
|
||||
if (hosttok)
|
||||
name = tal_strndup(cmd, buffer + hosttok->start,
|
||||
hosttok->end - hosttok->start);
|
||||
else if (ataddr)
|
||||
name = ataddr;
|
||||
else
|
||||
name = NULL;
|
||||
|
||||
/* Port without host name? */
|
||||
if (porttok && !name) {
|
||||
command_fail(cmd, "Can't specify port without host");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Was there parseable host name? */
|
||||
if (name) {
|
||||
/* Is there a port? */
|
||||
if (porttok) {
|
||||
u32 port;
|
||||
if (!json_tok_number(buffer, porttok, &port)) {
|
||||
command_fail(cmd, "Port %.*s not valid",
|
||||
porttok->end - porttok->start,
|
||||
buffer + porttok->start);
|
||||
return;
|
||||
}
|
||||
addr.port = port;
|
||||
} else {
|
||||
addr.port = DEFAULT_PORT;
|
||||
}
|
||||
if (!parse_wireaddr(name, &addr, addr.port) || !addr.port) {
|
||||
command_fail(cmd, "Host %s:%u not valid",
|
||||
name, addr.port);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tell it about the address. */
|
||||
msg = towire_gossipctl_peer_addrhint(cmd, &id, &addr);
|
||||
subd_send_msg(cmd->ld->gossip, take(msg));
|
||||
}
|
||||
|
||||
/* Now tell it to try reaching it. */
|
||||
msg = towire_gossipctl_reach_peer(cmd, &id);
|
||||
subd_send_msg(cmd->ld->gossip, take(msg));
|
||||
|
||||
/* Leave this here for gossip_peer_connected */
|
||||
new_connect(cmd->ld, &id, cmd);
|
||||
command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static const struct json_command connect_command = {
|
||||
"connect",
|
||||
json_connect,
|
||||
"Connect to {id} at {host} (which can end in ':port' if not default). "
|
||||
"{id} can also be of the form id@host"
|
||||
};
|
||||
AUTODATA(json_command, &connect_command);
|
||||
|
||||
struct getpeers_args {
|
||||
struct command *cmd;
|
||||
/* If non-NULL, they want logs too */
|
||||
|
@ -74,9 +74,6 @@ void peer_connected(struct lightningd *ld, const u8 *msg,
|
||||
/* This simply means we asked to reach a peer, but we already have it */
|
||||
void peer_already_connected(struct lightningd *ld, const u8 *msg);
|
||||
|
||||
/* We were unable to connect to the peer */
|
||||
void peer_connection_failed(struct lightningd *ld, const u8 *msg);
|
||||
|
||||
void peer_sent_nongossip(struct lightningd *ld,
|
||||
const struct pubkey *id,
|
||||
const struct wireaddr *addr,
|
||||
|
@ -62,6 +62,13 @@ void command_still_pending(struct command *cmd UNNEEDED)
|
||||
/* Generated stub for command_success */
|
||||
void command_success(struct command *cmd UNNEEDED, struct json_result *response UNNEEDED)
|
||||
{ fprintf(stderr, "command_success called!\n"); abort(); }
|
||||
/* Generated stub for connect_failed */
|
||||
void connect_failed(struct lightningd *ld UNNEEDED, const struct pubkey *id UNNEEDED,
|
||||
const char *error UNNEEDED)
|
||||
{ fprintf(stderr, "connect_failed called!\n"); abort(); }
|
||||
/* Generated stub for connect_succeeded */
|
||||
void connect_succeeded(struct lightningd *ld UNNEEDED, const struct pubkey *id UNNEEDED)
|
||||
{ fprintf(stderr, "connect_succeeded called!\n"); abort(); }
|
||||
/* Generated stub for derive_basepoints */
|
||||
bool derive_basepoints(const struct privkey *seed UNNEEDED,
|
||||
struct pubkey *funding_pubkey UNNEEDED,
|
||||
@ -105,9 +112,6 @@ bool fromwire_gossip_peer_already_connected(const void *p UNNEEDED, size_t *plen
|
||||
/* Generated stub for fromwire_gossip_peer_connected */
|
||||
bool fromwire_gossip_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_peer_connected called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_peer_connection_failed */
|
||||
bool fromwire_gossip_peer_connection_failed(const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED, u32 *timeout UNNEEDED, u32 *attempts UNNEEDED, bool *addr_unknown UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_peer_connection_failed called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_hsm_client_hsmfd_reply */
|
||||
bool fromwire_hsm_client_hsmfd_reply(const void *p UNNEEDED, size_t *plen UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_hsm_client_hsmfd_reply called!\n"); abort(); }
|
||||
@ -261,10 +265,6 @@ bool json_tok_bool(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, b
|
||||
bool json_tok_loglevel(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
enum log_level *level UNNEEDED)
|
||||
{ fprintf(stderr, "json_tok_loglevel called!\n"); abort(); }
|
||||
/* Generated stub for json_tok_number */
|
||||
bool json_tok_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
unsigned int *num UNNEEDED)
|
||||
{ fprintf(stderr, "json_tok_number called!\n"); abort(); }
|
||||
/* Generated stub for json_tok_pubkey */
|
||||
bool json_tok_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
|
||||
struct pubkey *pubkey UNNEEDED)
|
||||
|
Loading…
Reference in New Issue
Block a user