mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 06:41:44 +01:00
peer_failed: hand fds back to master when we fail.
master now hands it back to gossipd. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
f76ff90485
commit
02d469b3d4
7 changed files with 114 additions and 48 deletions
|
@ -33,7 +33,7 @@ void peer_failed_(int peer_fd, int gossip_fd,
|
||||||
msg = towire_status_peer_error(NULL, channel_id,
|
msg = towire_status_peer_error(NULL, channel_id,
|
||||||
desc, cs, gossip_index, msg);
|
desc, cs, gossip_index, msg);
|
||||||
tal_free(desc);
|
tal_free(desc);
|
||||||
status_send_fatal(take(msg));
|
status_send_fatal(take(msg), peer_fd, gossip_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're failing because peer sent us an error message */
|
/* We're failing because peer sent us an error message */
|
||||||
|
@ -44,10 +44,11 @@ void peer_failed_received_errmsg(int peer_fd, int gossip_fd,
|
||||||
{
|
{
|
||||||
u8 *msg = towire_status_peer_error(NULL, channel_id,
|
u8 *msg = towire_status_peer_error(NULL, channel_id,
|
||||||
desc, cs, gossip_index, NULL);
|
desc, cs, gossip_index, NULL);
|
||||||
status_send_fatal(take(msg));
|
status_send_fatal(take(msg), peer_fd, gossip_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_failed_connection_lost(void)
|
void peer_failed_connection_lost(void)
|
||||||
{
|
{
|
||||||
status_send_fatal(take(towire_status_peer_connection_lost(NULL)));
|
status_send_fatal(take(towire_status_peer_connection_lost(NULL)),
|
||||||
|
-1, -1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,12 +122,19 @@ static NORETURN void flush_and_exit(int reason)
|
||||||
exit(0x80 | (reason & 0xFF));
|
exit(0x80 | (reason & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
void status_send_fatal(const u8 *msg TAKES)
|
void status_send_fatal(const u8 *msg TAKES, int fd1, int fd2)
|
||||||
{
|
{
|
||||||
int reason = fromwire_peektype(msg);
|
int reason = fromwire_peektype(msg);
|
||||||
breakpoint();
|
breakpoint();
|
||||||
status_send(msg);
|
status_send(msg);
|
||||||
|
|
||||||
|
/* We don't support async fd passing here. */
|
||||||
|
if (fd1 != -1) {
|
||||||
|
assert(!status_conn);
|
||||||
|
fdpass_send(status_fd, fd1);
|
||||||
|
fdpass_send(status_fd, fd2);
|
||||||
|
}
|
||||||
|
|
||||||
flush_and_exit(reason);
|
flush_and_exit(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +148,8 @@ void status_failed(enum status_failreason reason, const char *fmt, ...)
|
||||||
str = tal_vfmt(NULL, fmt, ap);
|
str = tal_vfmt(NULL, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
status_send_fatal(take(towire_status_fail(NULL, reason, str)));
|
status_send_fatal(take(towire_status_fail(NULL, reason, str)),
|
||||||
|
-1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void master_badmsg(u32 type_expected, const u8 *msg)
|
void master_badmsg(u32 type_expected, const u8 *msg)
|
||||||
|
|
|
@ -51,5 +51,5 @@ void status_failed(enum status_failreason code,
|
||||||
* msg NULL == read failure. */
|
* msg NULL == read failure. */
|
||||||
void master_badmsg(u32 type_expected, const u8 *msg) NORETURN;
|
void master_badmsg(u32 type_expected, const u8 *msg) NORETURN;
|
||||||
|
|
||||||
void status_send_fatal(const u8 *msg TAKES) NORETURN;
|
void status_send_fatal(const u8 *msg TAKES, int fd1, int fd2) NORETURN;
|
||||||
#endif /* LIGHTNING_COMMON_STATUS_H */
|
#endif /* LIGHTNING_COMMON_STATUS_H */
|
||||||
|
|
|
@ -364,28 +364,60 @@ static void channel_config(struct lightningd *ld,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void channel_errmsg(struct channel *channel,
|
static void channel_errmsg(struct channel *channel,
|
||||||
enum side sender,
|
int peer_fd, int gossip_fd,
|
||||||
const struct channel_id *channel_id,
|
const struct crypto_state *cs,
|
||||||
const char *desc,
|
u64 gossip_index,
|
||||||
const u8 *errmsg)
|
const struct channel_id *channel_id,
|
||||||
|
const char *desc,
|
||||||
|
const u8 *err_for_them)
|
||||||
{
|
{
|
||||||
if (sender == LOCAL) {
|
struct lightningd *ld = channel->peer->ld;
|
||||||
/* If this is NULL, it means subd died. */
|
u8 *msg;
|
||||||
if (!errmsg) {
|
|
||||||
channel_fail_transient(channel, "%s: %s",
|
|
||||||
channel->owner->name, desc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise overwrite any error we have */
|
/* No peer fd means a subd crash or disconnection. */
|
||||||
if (!channel->error)
|
if (peer_fd == -1) {
|
||||||
channel->error = tal_dup_arr(channel, u8,
|
channel_fail_transient(channel, "%s: %s",
|
||||||
errmsg, tal_len(errmsg), 0);
|
channel->owner->name, desc);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do we have an error to send? */
|
||||||
|
if (err_for_them && !channel->error)
|
||||||
|
channel->error = tal_dup_arr(channel, u8,
|
||||||
|
err_for_them,
|
||||||
|
tal_len(err_for_them), 0);
|
||||||
|
|
||||||
|
/* BOLT #1:
|
||||||
|
*
|
||||||
|
* A sending node:
|
||||||
|
*...
|
||||||
|
* - when `channel_id` is 0:
|
||||||
|
* - MUST fail all channels.
|
||||||
|
* - MUST close the connection.
|
||||||
|
*/
|
||||||
|
/* FIXME: Gossipd closes connection, but doesn't fail channels. */
|
||||||
|
|
||||||
|
/* BOLT #1:
|
||||||
|
*
|
||||||
|
* A sending node:
|
||||||
|
* - when sending `error`:
|
||||||
|
* - MUST fail the channel referred to by the error message.
|
||||||
|
*...
|
||||||
|
* The receiving node:
|
||||||
|
* - upon receiving `error`:
|
||||||
|
* - MUST fail the channel referred to by the error message.
|
||||||
|
*/
|
||||||
channel_fail_permanent(channel, "%s: %s ERROR %s",
|
channel_fail_permanent(channel, "%s: %s ERROR %s",
|
||||||
channel->owner->name,
|
channel->owner->name,
|
||||||
sender == LOCAL ? "sent" : "received", desc);
|
err_for_them ? "sent" : "received", desc);
|
||||||
|
|
||||||
|
/* Hand back to gossipd, with any error packet. */
|
||||||
|
msg = towire_gossipctl_hand_back_peer(NULL, &channel->peer->id,
|
||||||
|
cs, gossip_index,
|
||||||
|
err_for_them);
|
||||||
|
subd_send_msg(ld->gossip, take(msg));
|
||||||
|
subd_send_fd(ld->gossip, peer_fd);
|
||||||
|
subd_send_fd(ld->gossip, gossip_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gossipd tells us a peer has connected */
|
/* Gossipd tells us a peer has connected */
|
||||||
|
@ -1340,10 +1372,12 @@ static bool tell_if_missing(const struct channel *channel,
|
||||||
|
|
||||||
/* Only error onchaind can get is if it dies. */
|
/* Only error onchaind can get is if it dies. */
|
||||||
static void onchain_error(struct channel *channel,
|
static void onchain_error(struct channel *channel,
|
||||||
enum side sender,
|
int peer_fd, int gossip_fd,
|
||||||
|
const struct crypto_state *cs,
|
||||||
|
u64 gossip_index,
|
||||||
const struct channel_id *channel_id,
|
const struct channel_id *channel_id,
|
||||||
const char *desc,
|
const char *desc,
|
||||||
const u8 *errmsg)
|
const u8 *err_for_them)
|
||||||
{
|
{
|
||||||
/* FIXME: re-launch? */
|
/* FIXME: re-launch? */
|
||||||
log_broken(channel->log, "%s", desc);
|
log_broken(channel->log, "%s", desc);
|
||||||
|
@ -2472,21 +2506,23 @@ static unsigned int opening_negotiation_failed(struct subd *openingd,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* errmsg == NULL for local if daemon died */
|
/* peer_fd == -1 for local if daemon died */
|
||||||
static void opening_channel_errmsg(struct uncommitted_channel *uc,
|
static void opening_channel_errmsg(struct uncommitted_channel *uc,
|
||||||
enum side sender,
|
int peer_fd, int gossip_fd,
|
||||||
|
const struct crypto_state *cs,
|
||||||
|
u64 gossip_index,
|
||||||
const struct channel_id *channel_id,
|
const struct channel_id *channel_id,
|
||||||
const char *desc,
|
const char *desc,
|
||||||
const u8 *errmsg)
|
const u8 *err_for_them)
|
||||||
{
|
{
|
||||||
if (uc->fc)
|
if (uc->fc)
|
||||||
command_fail(uc->fc->cmd, "%sERROR %s",
|
command_fail(uc->fc->cmd, "%sERROR %s",
|
||||||
sender == LOCAL ? (errmsg ? "sent " : "")
|
peer_fd == -1 ? ""
|
||||||
: "received ",
|
: (err_for_them ? "sent " : "received "),
|
||||||
desc);
|
desc);
|
||||||
|
|
||||||
log_info(uc->log, "%sERROR %s",
|
log_info(uc->log, "%sERROR %s",
|
||||||
sender == LOCAL ? (errmsg ? "sent " : "") : "received ",
|
peer_fd == -1 ? "" : (err_for_them ? "sent " : "received "),
|
||||||
desc);
|
desc);
|
||||||
tal_free(uc);
|
tal_free(uc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,7 +388,7 @@ static bool log_status_fail(struct subd *sd, const u8 *msg)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool handle_peer_error(struct subd *sd, const u8 *msg)
|
static bool handle_peer_error(struct subd *sd, const u8 *msg, int fds[2])
|
||||||
{
|
{
|
||||||
void *channel = sd->channel;
|
void *channel = sd->channel;
|
||||||
struct channel_id channel_id;
|
struct channel_id channel_id;
|
||||||
|
@ -402,11 +402,9 @@ static bool handle_peer_error(struct subd *sd, const u8 *msg)
|
||||||
&cs, &gossip_index, &err_for_them))
|
&cs, &gossip_index, &err_for_them))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* FIXME: hand back to gossipd! */
|
|
||||||
|
|
||||||
/* Don't free sd; we're may be about to free channel. */
|
/* Don't free sd; we're may be about to free channel. */
|
||||||
sd->channel = NULL;
|
sd->channel = NULL;
|
||||||
sd->errcb(channel, err_for_them ? LOCAL : REMOTE,
|
sd->errcb(channel, fds[0], fds[1], &cs, gossip_index,
|
||||||
&channel_id, desc, err_for_them);
|
&channel_id, desc, err_for_them);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -463,7 +461,15 @@ static struct io_plan *sd_msg_read(struct io_conn *conn, struct subd *sd)
|
||||||
if (sd->channel) {
|
if (sd->channel) {
|
||||||
switch ((enum peer_status)type) {
|
switch ((enum peer_status)type) {
|
||||||
case WIRE_STATUS_PEER_ERROR:
|
case WIRE_STATUS_PEER_ERROR:
|
||||||
if (!handle_peer_error(sd, sd->msg_in))
|
/* We expect 2 fds after this */
|
||||||
|
if (!sd->fds_in) {
|
||||||
|
/* Don't free msg_in: we go around again. */
|
||||||
|
tal_steal(sd, sd->msg_in);
|
||||||
|
tal_free(tmpctx);
|
||||||
|
plan = sd_collect_fds(conn, sd, 2);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!handle_peer_error(sd, sd->msg_in, sd->fds_in))
|
||||||
goto malformed;
|
goto malformed;
|
||||||
goto close;
|
goto close;
|
||||||
}
|
}
|
||||||
|
@ -564,7 +570,7 @@ static void destroy_subd(struct subd *sd)
|
||||||
if (!outer_transaction)
|
if (!outer_transaction)
|
||||||
db_begin_transaction(db);
|
db_begin_transaction(db);
|
||||||
if (sd->errcb)
|
if (sd->errcb)
|
||||||
sd->errcb(channel, LOCAL, NULL,
|
sd->errcb(channel, -1, -1, NULL, 0, NULL,
|
||||||
tal_fmt(sd, "Owning subdaemon %s died (%i)",
|
tal_fmt(sd, "Owning subdaemon %s died (%i)",
|
||||||
sd->name, status),
|
sd->name, status),
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -613,10 +619,12 @@ static struct subd *new_subd(struct lightningd *ld,
|
||||||
unsigned int (*msgcb)(struct subd *,
|
unsigned int (*msgcb)(struct subd *,
|
||||||
const u8 *, const int *fds),
|
const u8 *, const int *fds),
|
||||||
void (*errcb)(void *channel,
|
void (*errcb)(void *channel,
|
||||||
enum side sender,
|
int peer_fd, int gossip_fd,
|
||||||
|
const struct crypto_state *cs,
|
||||||
|
u64 gossip_index,
|
||||||
const struct channel_id *channel_id,
|
const struct channel_id *channel_id,
|
||||||
const char *desc,
|
const char *desc,
|
||||||
const u8 *errmsg),
|
const u8 *err_for_them),
|
||||||
va_list *ap)
|
va_list *ap)
|
||||||
{
|
{
|
||||||
struct subd *sd = tal(ld, struct subd);
|
struct subd *sd = tal(ld, struct subd);
|
||||||
|
@ -690,10 +698,12 @@ struct subd *new_channel_subd_(struct lightningd *ld,
|
||||||
unsigned int (*msgcb)(struct subd *, const u8 *,
|
unsigned int (*msgcb)(struct subd *, const u8 *,
|
||||||
const int *fds),
|
const int *fds),
|
||||||
void (*errcb)(void *channel,
|
void (*errcb)(void *channel,
|
||||||
enum side sender,
|
int peer_fd, int gossip_fd,
|
||||||
|
const struct crypto_state *cs,
|
||||||
|
u64 gossip_index,
|
||||||
const struct channel_id *channel_id,
|
const struct channel_id *channel_id,
|
||||||
const char *desc,
|
const char *desc,
|
||||||
const u8 *errmsg),
|
const u8 *err_for_them),
|
||||||
...)
|
...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <ccan/typesafe_cb/typesafe_cb.h>
|
#include <ccan/typesafe_cb/typesafe_cb.h>
|
||||||
#include <common/msg_queue.h>
|
#include <common/msg_queue.h>
|
||||||
|
|
||||||
|
struct crypto_state;
|
||||||
struct io_conn;
|
struct io_conn;
|
||||||
|
|
||||||
/* By convention, replies are requests + 100 */
|
/* By convention, replies are requests + 100 */
|
||||||
|
@ -36,12 +37,16 @@ struct subd {
|
||||||
unsigned (*msgcb)(struct subd *, const u8 *, const int *);
|
unsigned (*msgcb)(struct subd *, const u8 *, const int *);
|
||||||
const char *(*msgname)(int msgtype);
|
const char *(*msgname)(int msgtype);
|
||||||
|
|
||||||
/* Callback when an errormsg sent/received, or subd died. */
|
/* If peer_fd == -1, it was a disconnect/crash. Otherwise,
|
||||||
|
* sufficient information to hand back to gossipd, including the
|
||||||
|
* error message we sent them if any. */
|
||||||
void (*errcb)(void *channel,
|
void (*errcb)(void *channel,
|
||||||
enum side sender,
|
int peer_fd, int gossip_fd,
|
||||||
|
const struct crypto_state *cs,
|
||||||
|
u64 gossip_index,
|
||||||
const struct channel_id *channel_id,
|
const struct channel_id *channel_id,
|
||||||
const char *desc,
|
const char *desc,
|
||||||
const u8 *errmsg);
|
const u8 *err_for_them);
|
||||||
|
|
||||||
/* Buffer for input. */
|
/* Buffer for input. */
|
||||||
u8 *msg_in;
|
u8 *msg_in;
|
||||||
|
@ -103,16 +108,20 @@ struct subd *new_channel_subd_(struct lightningd *ld,
|
||||||
unsigned int (*msgcb)(struct subd *, const u8 *,
|
unsigned int (*msgcb)(struct subd *, const u8 *,
|
||||||
const int *fds),
|
const int *fds),
|
||||||
void (*errcb)(void *channel,
|
void (*errcb)(void *channel,
|
||||||
enum side sender,
|
int peer_fd, int gossip_fd,
|
||||||
|
const struct crypto_state *cs,
|
||||||
|
u64 gossip_index,
|
||||||
const struct channel_id *channel_id,
|
const struct channel_id *channel_id,
|
||||||
const char *desc,
|
const char *desc,
|
||||||
const u8 *errmsg),
|
const u8 *err_for_them),
|
||||||
...);
|
...);
|
||||||
|
|
||||||
#define new_channel_subd(ld, name, channel, log, msgname, msgcb, errcb, ...) \
|
#define new_channel_subd(ld, name, channel, log, msgname, msgcb, errcb, ...) \
|
||||||
new_channel_subd_((ld), (name), (channel), (log), (msgname), (msgcb), \
|
new_channel_subd_((ld), (name), (channel), (log), (msgname), (msgcb), \
|
||||||
typesafe_cb_postargs(void, void *, (errcb), \
|
typesafe_cb_postargs(void, void *, (errcb), \
|
||||||
(channel), enum side, \
|
(channel), int, int, \
|
||||||
|
const struct crypto_state *, \
|
||||||
|
u64, \
|
||||||
const struct channel_id *, \
|
const struct channel_id *, \
|
||||||
const char *, const u8 *), \
|
const char *, const u8 *), \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
|
|
|
@ -334,10 +334,12 @@ struct subd *new_channel_subd_(struct lightningd *ld UNNEEDED,
|
||||||
unsigned int (*msgcb)(struct subd * UNNEEDED, const u8 * UNNEEDED,
|
unsigned int (*msgcb)(struct subd * UNNEEDED, const u8 * UNNEEDED,
|
||||||
const int *fds) UNNEEDED,
|
const int *fds) UNNEEDED,
|
||||||
void (*errcb)(void *channel UNNEEDED,
|
void (*errcb)(void *channel UNNEEDED,
|
||||||
enum side sender UNNEEDED,
|
int peer_fd UNNEEDED, int gossip_fd UNNEEDED,
|
||||||
|
const struct crypto_state *cs UNNEEDED,
|
||||||
|
u64 gossip_index UNNEEDED,
|
||||||
const struct channel_id *channel_id UNNEEDED,
|
const struct channel_id *channel_id UNNEEDED,
|
||||||
const char *desc UNNEEDED,
|
const char *desc UNNEEDED,
|
||||||
const u8 *errmsg) UNNEEDED,
|
const u8 *err_for_them) UNNEEDED,
|
||||||
...)
|
...)
|
||||||
{ fprintf(stderr, "new_channel_subd_ called!\n"); abort(); }
|
{ fprintf(stderr, "new_channel_subd_ called!\n"); abort(); }
|
||||||
/* Generated stub for new_json_result */
|
/* Generated stub for new_json_result */
|
||||||
|
|
Loading…
Add table
Reference in a new issue