Browse Source

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>
ppa-0.6.1
Rusty Russell 7 years ago
parent
commit
02d469b3d4
  1. 7
      common/peer_failed.c
  2. 12
      common/status.c
  3. 2
      common/status.h
  4. 86
      lightningd/peer_control.c
  5. 30
      lightningd/subd.c
  6. 21
      lightningd/subd.h
  7. 6
      wallet/test/run-wallet.c

7
common/peer_failed.c

@ -33,7 +33,7 @@ void peer_failed_(int peer_fd, int gossip_fd,
msg = towire_status_peer_error(NULL, channel_id,
desc, cs, gossip_index, msg);
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 */
@ -44,10 +44,11 @@ void peer_failed_received_errmsg(int peer_fd, int gossip_fd,
{
u8 *msg = towire_status_peer_error(NULL, channel_id,
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)
{
status_send_fatal(take(towire_status_peer_connection_lost(NULL)));
status_send_fatal(take(towire_status_peer_connection_lost(NULL)),
-1, -1);
}

12
common/status.c

@ -122,12 +122,19 @@ static NORETURN void flush_and_exit(int reason)
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);
breakpoint();
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);
}
@ -141,7 +148,8 @@ void status_failed(enum status_failreason reason, const char *fmt, ...)
str = tal_vfmt(NULL, fmt, 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)

2
common/status.h

@ -51,5 +51,5 @@ void status_failed(enum status_failreason code,
* msg NULL == read failure. */
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 */

86
lightningd/peer_control.c

@ -364,28 +364,60 @@ static void channel_config(struct lightningd *ld,
};
static void channel_errmsg(struct channel *channel,
enum side sender,
const struct channel_id *channel_id,
const char *desc,
const u8 *errmsg)
{
if (sender == LOCAL) {
/* If this is NULL, it means subd died. */
if (!errmsg) {
channel_fail_transient(channel, "%s: %s",
channel->owner->name, desc);
return;
}
int peer_fd, int gossip_fd,
const struct crypto_state *cs,
u64 gossip_index,
const struct channel_id *channel_id,
const char *desc,
const u8 *err_for_them)
{
struct lightningd *ld = channel->peer->ld;
u8 *msg;
/* Otherwise overwrite any error we have */
if (!channel->error)
channel->error = tal_dup_arr(channel, u8,
errmsg, tal_len(errmsg), 0);
/* No peer fd means a subd crash or disconnection. */
if (peer_fd == -1) {
channel_fail_transient(channel, "%s: %s",
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->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 */
@ -1340,10 +1372,12 @@ static bool tell_if_missing(const struct channel *channel,
/* Only error onchaind can get is if it dies. */
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 char *desc,
const u8 *errmsg)
const u8 *err_for_them)
{
/* FIXME: re-launch? */
log_broken(channel->log, "%s", desc);
@ -2472,21 +2506,23 @@ static unsigned int opening_negotiation_failed(struct subd *openingd,
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,
enum side sender,
int peer_fd, int gossip_fd,
const struct crypto_state *cs,
u64 gossip_index,
const struct channel_id *channel_id,
const char *desc,
const u8 *errmsg)
const u8 *err_for_them)
{
if (uc->fc)
command_fail(uc->fc->cmd, "%sERROR %s",
sender == LOCAL ? (errmsg ? "sent " : "")
: "received ",
peer_fd == -1 ? ""
: (err_for_them ? "sent " : "received "),
desc);
log_info(uc->log, "%sERROR %s",
sender == LOCAL ? (errmsg ? "sent " : "") : "received ",
peer_fd == -1 ? "" : (err_for_them ? "sent " : "received "),
desc);
tal_free(uc);
}

30
lightningd/subd.c

@ -388,7 +388,7 @@ static bool log_status_fail(struct subd *sd, const u8 *msg)
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;
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))
return false;
/* FIXME: hand back to gossipd! */
/* Don't free sd; we're may be about to free channel. */
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);
return true;
}
@ -463,7 +461,15 @@ static struct io_plan *sd_msg_read(struct io_conn *conn, struct subd *sd)
if (sd->channel) {
switch ((enum peer_status)type) {
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 close;
}
@ -564,7 +570,7 @@ static void destroy_subd(struct subd *sd)
if (!outer_transaction)
db_begin_transaction(db);
if (sd->errcb)
sd->errcb(channel, LOCAL, NULL,
sd->errcb(channel, -1, -1, NULL, 0, NULL,
tal_fmt(sd, "Owning subdaemon %s died (%i)",
sd->name, status),
NULL);
@ -613,10 +619,12 @@ static struct subd *new_subd(struct lightningd *ld,
unsigned int (*msgcb)(struct subd *,
const u8 *, const int *fds),
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 char *desc,
const u8 *errmsg),
const u8 *err_for_them),
va_list *ap)
{
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 *,
const int *fds),
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 char *desc,
const u8 *errmsg),
const u8 *err_for_them),
...)
{
va_list ap;

21
lightningd/subd.h

@ -8,6 +8,7 @@
#include <ccan/typesafe_cb/typesafe_cb.h>
#include <common/msg_queue.h>
struct crypto_state;
struct io_conn;
/* By convention, replies are requests + 100 */
@ -36,12 +37,16 @@ struct subd {
unsigned (*msgcb)(struct subd *, const u8 *, const int *);
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,
enum side sender,
int peer_fd, int gossip_fd,
const struct crypto_state *cs,
u64 gossip_index,
const struct channel_id *channel_id,
const char *desc,
const u8 *errmsg);
const u8 *err_for_them);
/* Buffer for input. */
u8 *msg_in;
@ -103,16 +108,20 @@ struct subd *new_channel_subd_(struct lightningd *ld,
unsigned int (*msgcb)(struct subd *, const u8 *,
const int *fds),
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 char *desc,
const u8 *errmsg),
const u8 *err_for_them),
...);
#define new_channel_subd(ld, name, channel, log, msgname, msgcb, errcb, ...) \
new_channel_subd_((ld), (name), (channel), (log), (msgname), (msgcb), \
typesafe_cb_postargs(void, void *, (errcb), \
(channel), enum side, \
(channel), int, int, \
const struct crypto_state *, \
u64, \
const struct channel_id *, \
const char *, const u8 *), \
__VA_ARGS__)

6
wallet/test/run-wallet.c

@ -334,10 +334,12 @@ struct subd *new_channel_subd_(struct lightningd *ld UNNEEDED,
unsigned int (*msgcb)(struct subd * UNNEEDED, const u8 * UNNEEDED,
const int *fds) 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 char *desc UNNEEDED,
const u8 *errmsg) UNNEEDED,
const u8 *err_for_them) UNNEEDED,
...)
{ fprintf(stderr, "new_channel_subd_ called!\n"); abort(); }
/* Generated stub for new_json_result */

Loading…
Cancel
Save