mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-02 12:44:26 +01:00
dev_disconnect: new option to stop using connection, but don't close.
This allows us to ensure a packet is read by the other end, but we don't read anything else from them or write anything to them. Using '+' is similar, but because it closes the connection, the peer might notice before receiving the packet (such as if it does a write). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES)
|
||||
{
|
||||
#if DEVELOPER
|
||||
bool post_sabotage = false;
|
||||
bool post_sabotage = false, post_close;
|
||||
int type = fromwire_peektype(msg);
|
||||
#endif
|
||||
u8 *enc;
|
||||
@@ -28,18 +28,23 @@ void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES)
|
||||
#if DEVELOPER
|
||||
switch (dev_disconnect(type)) {
|
||||
case DEV_DISCONNECT_BEFORE:
|
||||
dev_sabotage_fd(pps->peer_fd);
|
||||
dev_sabotage_fd(pps->peer_fd, true);
|
||||
peer_failed_connection_lost();
|
||||
case DEV_DISCONNECT_DROPPKT:
|
||||
enc = tal_free(enc); /* FALL THRU */
|
||||
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 (!write_all(pps->peer_fd, enc, tal_count(enc)))
|
||||
@@ -48,7 +53,7 @@ void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES)
|
||||
|
||||
#if DEVELOPER
|
||||
if (post_sabotage)
|
||||
dev_sabotage_fd(pps->peer_fd);
|
||||
dev_sabotage_fd(pps->peer_fd, post_close);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -90,16 +90,13 @@ enum dev_disconnect dev_disconnect(int pkt_type)
|
||||
return dev_disconnect_line[0];
|
||||
}
|
||||
|
||||
void dev_sabotage_fd(int fd)
|
||||
void dev_sabotage_fd(int fd, bool close_fd)
|
||||
{
|
||||
int fds[2];
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0)
|
||||
err(1, "dev_sabotage_fd: creating socketpair");
|
||||
|
||||
/* Close one. */
|
||||
close(fds[0]);
|
||||
|
||||
#if defined(TCP_NODELAY)
|
||||
/* On Linux, at least, this flushes. */
|
||||
int opt = TCP_NODELAY;
|
||||
@@ -108,6 +105,14 @@ void dev_sabotage_fd(int fd)
|
||||
#else
|
||||
#error No TCP_NODELAY?
|
||||
#endif
|
||||
|
||||
/* Move fd out the way if we don't want to close it. */
|
||||
if (!close_fd)
|
||||
dup(fd);
|
||||
else
|
||||
/* Close other end of socket. */
|
||||
close(fds[0]);
|
||||
|
||||
/* Move other over to the fd we want to sabotage. */
|
||||
dup2(fds[1], fd);
|
||||
close(fds[1]);
|
||||
|
||||
@@ -15,13 +15,15 @@ enum dev_disconnect {
|
||||
DEV_DISCONNECT_DROPPKT = '@',
|
||||
/* Swallow all writes from now on, and do no more reads. */
|
||||
DEV_DISCONNECT_BLACKHOLE = '0',
|
||||
/* Don't use connection after sending packet, but don't close. */
|
||||
DEV_DISCONNECT_DISABLE_AFTER = 'x',
|
||||
};
|
||||
|
||||
/* Force a close fd before or after a certain packet type */
|
||||
enum dev_disconnect dev_disconnect(int pkt_type);
|
||||
|
||||
/* Make next write on fd fail as if they'd disconnected. */
|
||||
void dev_sabotage_fd(int fd);
|
||||
void dev_sabotage_fd(int fd, bool close_fd);
|
||||
|
||||
/* No more data to arrive, what's written is swallowed. */
|
||||
void dev_blackhole_fd(int fd);
|
||||
|
||||
@@ -132,7 +132,14 @@ static struct io_plan *read_init(struct io_conn *conn, struct peer *peer)
|
||||
static struct io_plan *peer_write_postclose(struct io_conn *conn,
|
||||
struct peer *peer)
|
||||
{
|
||||
dev_sabotage_fd(io_conn_fd(conn));
|
||||
dev_sabotage_fd(io_conn_fd(conn), true);
|
||||
return read_init(conn, peer);
|
||||
}
|
||||
|
||||
static struct io_plan *peer_write_post_sabotage(struct io_conn *conn,
|
||||
struct peer *peer)
|
||||
{
|
||||
dev_sabotage_fd(io_conn_fd(conn), false);
|
||||
return read_init(conn, peer);
|
||||
}
|
||||
#endif
|
||||
@@ -197,7 +204,7 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
|
||||
#if DEVELOPER
|
||||
switch (dev_disconnect(WIRE_INIT)) {
|
||||
case DEV_DISCONNECT_BEFORE:
|
||||
dev_sabotage_fd(io_conn_fd(conn));
|
||||
dev_sabotage_fd(io_conn_fd(conn), true);
|
||||
break;
|
||||
case DEV_DISCONNECT_DROPPKT:
|
||||
peer->msg = tal_free(peer->msg); /* FALL THRU */
|
||||
@@ -209,6 +216,9 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
|
||||
break;
|
||||
case DEV_DISCONNECT_NORMAL:
|
||||
break;
|
||||
case DEV_DISCONNECT_DISABLE_AFTER:
|
||||
next = peer_write_post_sabotage;
|
||||
break;
|
||||
}
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ void status_fmt(enum log_level level,
|
||||
}
|
||||
|
||||
#if DEVELOPER
|
||||
void dev_sabotage_fd(int fd)
|
||||
void dev_sabotage_fd(int fd, bool close_fd)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user