Skip to content

Commit

Permalink
connectd: do dev_disconnect logic.
Browse files Browse the repository at this point in the history
As connectd handles more packets itself, or diverts them to/from gossipd,
it's the only place we can implement the dev_disconnect logic.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Jan 20, 2022
1 parent 9c0bb44 commit 7a51411
Show file tree
Hide file tree
Showing 17 changed files with 71 additions and 70 deletions.
1 change: 0 additions & 1 deletion channeld/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ CHANNELD_COMMON_OBJS := \
common/daemon.o \
common/daemon_conn.o \
common/derive_basepoints.o \
common/dev_disconnect.o \
common/ecdh_hsmd.o \
common/features.o \
common/fee_states.o \
Expand Down
1 change: 0 additions & 1 deletion channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <channeld/full_channel.h>
#include <channeld/watchtower.h>
#include <common/billboard.h>
#include <common/dev_disconnect.h>
#include <common/ecdh_hsmd.h>
#include <common/gossip_store.h>
#include <common/key_derive.h>
Expand Down
1 change: 0 additions & 1 deletion closingd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ CLOSINGD_COMMON_OBJS := \
common/daemon.o \
common/daemon_conn.o \
common/derive_basepoints.o \
common/dev_disconnect.o \
common/gossip_rcvd_filter.o \
common/gossip_store.o \
common/htlc_wire.o \
Expand Down
8 changes: 5 additions & 3 deletions common/dev_disconnect.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ void dev_disconnect_init(int fd)
dev_disconnect_fd = fd;
}

enum dev_disconnect dev_disconnect(int pkt_type)
enum dev_disconnect dev_disconnect(const struct node_id *id, int pkt_type)
{
if (dev_disconnect_fd == -1)
return DEV_DISCONNECT_NORMAL;

if (!dev_disconnect_count)
next_dev_disconnect();

if (!streq(peer_wire_name(pkt_type), dev_disconnect_line+1))
if (!dev_disconnect_line[0]
|| !streq(peer_wire_name(pkt_type), dev_disconnect_line+1))
return DEV_DISCONNECT_NORMAL;

if (--dev_disconnect_count != 0) {
Expand All @@ -70,7 +71,8 @@ enum dev_disconnect dev_disconnect(int pkt_type)
err(1, "lseek failure");
}

status_debug("dev_disconnect: %s", dev_disconnect_line);
status_peer_debug(id, "dev_disconnect: %s (%s)", dev_disconnect_line,
peer_wire_name(pkt_type));
return dev_disconnect_line[0];
}

Expand Down
4 changes: 3 additions & 1 deletion common/dev_disconnect.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <stdbool.h>

#if DEVELOPER
struct node_id;

enum dev_disconnect {
/* Do nothing. */
DEV_DISCONNECT_NORMAL = '=',
Expand All @@ -18,7 +20,7 @@ enum dev_disconnect {
};

/* Force a close fd before or after a certain packet type */
enum dev_disconnect dev_disconnect(int pkt_type);
enum dev_disconnect dev_disconnect(const struct node_id *id, int pkt_type);

/* Make next write on fd fail as if they'd disconnected. */
void dev_sabotage_fd(int fd, bool close_fd);
Expand Down
31 changes: 0 additions & 31 deletions common/peer_io.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "config.h"
#include <ccan/read_write_all/read_write_all.h>
#include <common/cryptomsg.h>
#include <common/dev_disconnect.h>
#include <common/peer_failed.h>
#include <common/peer_io.h>
#include <common/per_peer_state.h>
Expand All @@ -17,40 +16,10 @@

void peer_write(struct per_peer_state *pps, const void *msg TAKES)
{
#if DEVELOPER
bool post_sabotage = false, post_close;
int type = fromwire_peektype(msg);
#endif

status_peer_io(LOG_IO_OUT, NULL, msg);

#if DEVELOPER
switch (dev_disconnect(type)) {
case DEV_DISCONNECT_BEFORE:
dev_sabotage_fd(pps->peer_fd, true);
peer_failed_connection_lost();
case DEV_DISCONNECT_AFTER:
post_sabotage = true;
post_close = true;
break;
case DEV_DISCONNECT_BLACKHOLE:
dev_blackhole_fd(pps->peer_fd);
break;
case DEV_DISCONNECT_NORMAL:
break;
case DEV_DISCONNECT_DISABLE_AFTER:
post_sabotage = true;
post_close = false;
break;
}
#endif
if (!wire_sync_write(pps->peer_fd, msg))
peer_failed_connection_lost();

#if DEVELOPER
if (post_sabotage)
dev_sabotage_fd(pps->peer_fd, post_close);
#endif
}

/* We're happy for the kernel to batch update and gossip messages, but a
Expand Down
10 changes: 0 additions & 10 deletions common/subdaemon.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "config.h"
#include <common/dev_disconnect.h>
#include <common/status.h>
#include <common/subdaemon.h>
#include <common/version.h>
Expand Down Expand Up @@ -33,14 +32,5 @@ void subdaemon_setup(int argc, char *argv[])

daemon_maybe_debug(argv);

#if DEVELOPER
for (int i = 1; i < argc; i++) {
if (strstarts(argv[i], "--dev-disconnect=")) {
dev_disconnect_init(atoi(argv[i]
+ strlen("--dev-disconnect=")));
}
}
#endif

daemon_setup(argv[0], status_backtrace_print, status_backtrace_exit);
}
9 changes: 8 additions & 1 deletion connectd/connectd.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <common/bech32.h>
#include <common/bech32_util.h>
#include <common/daemon_conn.h>
#include <common/dev_disconnect.h>
#include <common/ecdh_hsmd.h>
#include <common/jsonrpc_errors.h>
#include <common/memleak.h>
Expand Down Expand Up @@ -1598,6 +1599,7 @@ static void connect_init(struct daemon *daemon, const u8 *msg)
enum addr_listen_announce *proposed_listen_announce;
struct wireaddr *announcable;
char *tor_password;
bool dev_disconnect;

/* Fields which require allocation are allocated off daemon */
if (!fromwire_connectd_init(
Expand All @@ -1613,7 +1615,8 @@ static void connect_init(struct daemon *daemon, const u8 *msg)
&daemon->use_v3_autotor,
&daemon->timeout_secs,
&daemon->websocket_helper,
&daemon->websocket_port)) {
&daemon->websocket_port,
&dev_disconnect)) {
/* This is a helper which prints the type expected and the actual
* message, then exits (it should never be called!). */
master_badmsg(WIRE_CONNECTD_INIT, msg);
Expand Down Expand Up @@ -1657,6 +1660,10 @@ static void connect_init(struct daemon *daemon, const u8 *msg)
take(towire_connectd_init_reply(NULL,
binding,
announcable)));
#if DEVELOPER
if (dev_disconnect)
dev_disconnect_init(5);
#endif
}

/*~ lightningd tells us to go! */
Expand Down
2 changes: 2 additions & 0 deletions connectd/connectd_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ msgdata,connectd_init,use_v3_autotor,bool,
msgdata,connectd_init,timeout_secs,u32,
msgdata,connectd_init,websocket_helper,wirestring,
msgdata,connectd_init,websocket_port,u16,
# If this is set, then fd 5 is dev_disconnect_fd.
msgdata,connectd_init,dev_disconnect,bool,

# Connectd->master, here are the addresses I bound, can announce.
msgtype,connectd_init_reply,2100
Expand Down
38 changes: 38 additions & 0 deletions connectd/multiplex.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
#include <assert.h>
#include <ccan/io/io.h>
#include <common/cryptomsg.h>
#include <common/dev_disconnect.h>
#include <common/per_peer_state.h>
#include <common/status.h>
#include <common/utils.h>
#include <connectd/multiplex.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <wire/wire.h>
#include <wire/wire_io.h>

void queue_peer_msg(struct peer *peer, const u8 *msg TAKES)
Expand All @@ -32,12 +34,48 @@ static struct io_plan *after_final_msg(struct io_conn *peer_conn,
return io_close(peer_conn);
}

#if DEVELOPER
static struct io_plan *write_to_peer(struct io_conn *peer_conn,
struct peer *peer);

static struct io_plan *dev_leave_hanging(struct io_conn *peer_conn,
struct peer *peer)
{
/* We don't tell the peer we're disconnecting, but from now on
* our writes go nowhere, and there's nothing to read. */
dev_sabotage_fd(io_conn_fd(peer_conn), false);
return write_to_peer(peer_conn, peer);
}
#endif /* DEVELOPER */

static struct io_plan *encrypt_and_send(struct peer *peer,
const u8 *msg TAKES,
struct io_plan *(*next)
(struct io_conn *peer_conn,
struct peer *peer))
{
#if DEVELOPER
int type = fromwire_peektype(msg);

switch (dev_disconnect(&peer->id, type)) {
case DEV_DISCONNECT_BEFORE:
if (taken(msg))
tal_free(msg);
return io_close(peer->to_peer);
case DEV_DISCONNECT_AFTER:
next = (void *)io_close_cb;
break;
case DEV_DISCONNECT_BLACKHOLE:
dev_blackhole_fd(io_conn_fd(peer->to_peer));
break;
case DEV_DISCONNECT_NORMAL:
break;
case DEV_DISCONNECT_DISABLE_AFTER:
next = dev_leave_hanging;
break;
}
#endif

/* We free this and the encrypted version in next write_to_peer */
peer->sent_to_peer = cryptomsg_encrypt_msg(peer, &peer->cs, msg);
return io_write(peer->to_peer,
Expand Down
2 changes: 1 addition & 1 deletion connectd/peer_exchange_initmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,

next = read_init;
#if DEVELOPER
switch (dev_disconnect(WIRE_INIT)) {
switch (dev_disconnect(&peer->id, WIRE_INIT)) {
case DEV_DISCONNECT_BEFORE:
dev_sabotage_fd(io_conn_fd(conn), true);
break;
Expand Down
4 changes: 0 additions & 4 deletions hsmd/hsmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ static bool is_lightningd(const struct client *client)
return client == dbid_zero_clients[0];
}

/* FIXME: This is used by debug.c. Doesn't apply to us, but lets us link. */
extern void dev_disconnect_init(int fd);
void dev_disconnect_init(int fd UNUSED) { }

/* Pre-declare this, due to mutual recursion */
static struct io_plan *handle_client(struct io_conn *conn, struct client *c);

Expand Down
11 changes: 9 additions & 2 deletions lightningd/connect_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,13 @@ int connectd_init(struct lightningd *ld)

ld->connectd = new_global_subd(ld, "lightning_connectd",
connectd_wire_name, connectd_msg,
take(&hsmfd), take(&fds[1]), NULL);
take(&hsmfd), take(&fds[1]),
#if DEVELOPER
/* Not take(): we share it */
ld->dev_disconnect_fd >= 0 ?
&ld->dev_disconnect_fd : NULL,
#endif
NULL);
if (!ld->connectd)
err(1, "Could not subdaemon connectd");

Expand All @@ -385,7 +391,8 @@ int connectd_init(struct lightningd *ld)
ld->config.use_v3_autotor,
ld->config.connection_timeout_secs,
websocket_helper_path,
ld->websocket_port);
ld->websocket_port,
IFDEV(ld->dev_disconnect_fd >= 0, false));

subd_req(ld->connectd, ld->connectd, take(msg), -1, 0,
connect_init_done, NULL);
Expand Down
14 changes: 3 additions & 11 deletions lightningd/subd.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ static void close_taken_fds(va_list *ap)
/* We use sockets, not pipes, because fds are bidir. */
static int subd(const char *path, const char *name,
const char *debug_subdaemon,
int *msgfd, int dev_disconnect_fd,
int *msgfd,
bool io_logging,
va_list *ap)
{
Expand All @@ -212,7 +212,7 @@ static int subd(const char *path, const char *name,

if (childpid == 0) {
size_t num_args;
char *args[] = { NULL, NULL, NULL, NULL, NULL };
char *args[] = { NULL, NULL, NULL, NULL };
int **fds = tal_arr(tmpctx, int *, 3);
int stdoutfd = STDOUT_FILENO, stderrfd = STDERR_FILENO;

Expand All @@ -230,10 +230,6 @@ static int subd(const char *path, const char *name,
tal_arr_expand(&fds, fd);
}

/* If we have a dev_disconnect_fd, add it after. */
if (dev_disconnect_fd != -1)
tal_arr_expand(&fds, &dev_disconnect_fd);

/* Finally, the fd to report exec errors on */
tal_arr_expand(&fds, &execfail[1]);

Expand All @@ -248,8 +244,6 @@ static int subd(const char *path, const char *name,
if (io_logging)
args[num_args++] = "--log-io";
#if DEVELOPER
if (dev_disconnect_fd != -1)
args[num_args++] = tal_fmt(NULL, "--dev-disconnect=%i", dev_disconnect_fd);
if (debug_subdaemon && strends(name, debug_subdaemon))
args[num_args++] = "--debugger";
#endif
Expand Down Expand Up @@ -700,7 +694,6 @@ static struct subd *new_subd(struct lightningd *ld,
struct subd *sd = tal(ld, struct subd);
int msg_fd;
const char *debug_subd = NULL;
int disconnect_fd = -1;
const char *shortname;

assert(name != NULL);
Expand All @@ -720,13 +713,12 @@ static struct subd *new_subd(struct lightningd *ld,

#if DEVELOPER
debug_subd = ld->dev_debug_subprocess;
disconnect_fd = ld->dev_disconnect_fd;
#endif /* DEVELOPER */

const char *path = subdaemon_path(tmpctx, ld, name);

sd->pid = subd(path, name, debug_subd,
&msg_fd, disconnect_fd,
&msg_fd,
/* We only turn on subdaemon io logging if we're going
* to print it: too stressful otherwise! */
log_print_level(sd->log) < LOG_DBG,
Expand Down
1 change: 0 additions & 1 deletion onchaind/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ ONCHAIND_COMMON_OBJS := \
common/daemon.o \
common/daemon_conn.o \
common/derive_basepoints.o \
common/dev_disconnect.o \
common/status_wiregen.o \
common/htlc_tx.o \
common/htlc_wire.o \
Expand Down
1 change: 0 additions & 1 deletion openingd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ OPENINGD_COMMON_OBJS := \
common/daemon.o \
common/daemon_conn.o \
common/derive_basepoints.o \
common/dev_disconnect.o \
common/features.o \
common/fee_states.o \
common/gossip_rcvd_filter.o \
Expand Down
3 changes: 2 additions & 1 deletion tests/test_gossip.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,8 @@ def test_gossip_no_empty_announcements(node_factory, bitcoind):
# l3 sends CHANNEL_ANNOUNCEMENT to l2, but not CHANNEL_UDPATE.
l1, l2, l3, l4 = node_factory.line_graph(4, opts=[{'log-level': 'io'},
{'log-level': 'io'},
{'disconnect': ['+WIRE_CHANNEL_ANNOUNCEMENT'],
# Writes to l4 first, then l2
{'disconnect': ['+WIRE_CHANNEL_ANNOUNCEMENT*2'],
'may_reconnect': True},
{'may_reconnect': True}],
fundchannel=False)
Expand Down

0 comments on commit 7a51411

Please sign in to comment.