Files
lightning/common/read_peer_msg.c
Rusty Russell f76ff90485 status: split off error messages into a new 'peer_status' type.
Several daemons (onchaind, hsm) want to use the status messages, but
don't communicate with peers.  The coming changes made them drag in
more code they didn't need, so instead we have a different
non-overlapping type.

We combine the status_received_errmsg and status_sent_errmsg
into a single status_peer_error, with the presence or not of the
'error_for_them' field indicating direction. 

We also rename status_fatal_connection_lost() to
peer_failed_connection_lost() to fit in.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2018-02-19 02:56:51 +00:00

140 lines
3.6 KiB
C

#include <ccan/structeq/structeq.h>
#include <common/crypto_sync.h>
#include <common/peer_failed.h>
#include <common/ping.h>
#include <common/read_peer_msg.h>
#include <common/status.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <common/wire_error.h>
#include <errno.h>
#include <wire/peer_wire.h>
#include <wire/wire_sync.h>
static void handle_ping(const u8 *msg,
int peer_fd,
struct crypto_state *cs,
const struct channel_id *channel,
bool (*send_reply)(struct crypto_state *, int,
const u8 *, void *),
void (*io_error)(void *),
void *arg)
{
u8 *pong;
if (!check_ping_make_pong(msg, msg, &pong)) {
send_reply(cs, peer_fd,
take(towire_errorfmt(msg, channel,
"Bad ping %s",
tal_hex(msg, msg))), arg);
io_error(arg);
}
status_debug("Got ping, sending %s", pong ?
wire_type_name(fromwire_peektype(pong))
: "nothing");
if (pong && !send_reply(cs, peer_fd, pong, arg))
io_error(arg);
}
u8 *read_peer_msg_(const tal_t *ctx,
int peer_fd, int gossip_fd,
struct crypto_state *cs, u64 gossip_index,
const struct channel_id *channel,
bool (*send_reply)(struct crypto_state *cs, int fd,
const u8 *TAKES, void *arg),
void (*io_error)(void *arg),
void (*err_pkt)(int peer_fd, int gossip_fd,
struct crypto_state *cs, u64 gossip_index,
const char *desc,
const struct channel_id *channel_id,
void *arg),
void *arg)
{
u8 *msg;
struct channel_id chanid;
msg = sync_crypto_read(ctx, cs, peer_fd);
if (!msg)
io_error(arg);
if (is_gossip_msg(msg)) {
/* Forward to gossip daemon */
wire_sync_write(gossip_fd, take(msg));
return NULL;
}
if (fromwire_peektype(msg) == WIRE_PING) {
handle_ping(msg, peer_fd, cs, channel,
send_reply, io_error, arg);
return tal_free(msg);
}
if (fromwire_peektype(msg) == WIRE_ERROR) {
char *err = sanitize_error(msg, msg, &chanid);
/* BOLT #1:
*
* The channel is referred to by `channel_id`, unless
* `channel_id` is 0 (i.e. all bytes are 0), in which
* case it refers to all channels.
* ...
* The receiving node:
* - upon receiving `error`:
* - MUST fail the channel referred to by the error
* message.
* - if no existing channel is referred to by the
* message:
* - MUST ignore the message.
*/
if (structeq(&chanid, channel) || channel_id_is_all(&chanid))
err_pkt(peer_fd, gossip_fd, cs, gossip_index,
err, &chanid, arg);
return tal_free(msg);
}
/* They're talking about a different channel? */
if (extract_channel_id(msg, &chanid)
&& !structeq(&chanid, channel)) {
status_trace("Rejecting %s for unknown channel_id %s",
wire_type_name(fromwire_peektype(msg)),
type_to_string(msg, struct channel_id, &chanid));
if (!send_reply(cs, peer_fd,
take(towire_errorfmt(msg, &chanid,
"Multiple channels"
" unsupported")),
arg))
io_error(arg);
return tal_free(msg);
}
return msg;
}
/* Helper: sync_crypto_write, with extra args it ignores */
bool sync_crypto_write_arg(struct crypto_state *cs, int fd, const u8 *msg,
void *unused)
{
return sync_crypto_write(cs, fd, msg);
}
/* Helper: calls peer_failed_connection_lost. */
void status_fail_io(void *unused)
{
peer_failed_connection_lost();
}
/* Helper: calls peer_failed_received_errmsg() */
void status_fail_errpkt(int peer_fd, int gossip_fd,
struct crypto_state *cs, u64 gossip_index,
const char *desc,
const struct channel_id *channel_id,
void *unused)
{
peer_failed_received_errmsg(peer_fd, gossip_fd,
cs, gossip_index, desc, channel_id);
}