From b9a2400a5feaf75f3ca47363da0e8b96fe8e6fdd Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 31 May 2018 11:43:25 +0200 Subject: [PATCH] gossip: Simplify message handling in gossip_store `gossip_store_add` is the entry point for messages from the network, so it should do the bookkeeping and disable on failures. `gossip_store_append` is the shared function that wraps messages and writes it to the given file. This is shared between the from network path and the compaction path, so we don't directly use the `gossip_store` instance, but `fd`s. Signed-off-by: Christian Decker --- gossipd/gossip_store.c | 149 +++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 89 deletions(-) diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index e24c085f3..82fe0e2ab 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -75,53 +75,8 @@ struct gossip_store *gossip_store_new(const tal_t *ctx, return gs; } -/** - * Given a message and a file descriptor append the message to it. - * - * Returns true on success, false on error. - */ -static bool gossip_store_file_append(int fd, const u8 *msg) -{ - u32 msglen = tal_len(msg); - beint32_t checksum, belen = cpu_to_be32(msglen); - - /* Only give error message once. */ - if (fd == -1) - return true; - - checksum = cpu_to_be32(crc32c(0, msg, msglen)); - - return (write(fd, &belen, sizeof(belen)) == sizeof(belen) && - write(fd, &checksum, sizeof(checksum)) == sizeof(checksum) && - write(fd, msg, msglen) == msglen); -} - -/** - * Write an incoming message to the `gossip_store` - * - * @param gs The gossip_store to write to - * @param msg The message to write - * @return The newly created and initialized `gossip_store` - */ -static void gossip_store_append(struct gossip_store *gs, const u8 *msg) -{ - size_t stale; - if (!gossip_store_file_append(gs->fd, msg)) { - status_broken("Failed writing to gossip store: %s", - strerror(errno)); - gs->fd = -1; - return; - } - - gs->count++; - stale = gs->count - gs->broadcast->count; - - if (gs->count >= 100 && stale * MAX_COUNT_TO_STALE_RATE > gs->count) { - /* FIXME(cdecker) Implement rewriting of gossip_store */ - } -} - -static void gossip_store_add_channel_announcement(struct gossip_store *gs, +static u8 *gossip_store_wrap_channel_announcement(const tal_t *ctx, + struct routing_state *rstate, const u8 *gossip_msg) { secp256k1_ecdsa_signature node_signature_1, node_signature_2; @@ -143,63 +98,79 @@ static void gossip_store_add_channel_announcement(struct gossip_store *gs, status_failed(STATUS_FAIL_INTERNAL_ERROR, "Error parsing channel_announcement"); - struct chan *chan = get_channel(gs->rstate, &scid); + struct chan *chan = get_channel(rstate, &scid); assert(chan && chan->satoshis > 0); - u8 *msg = towire_gossip_store_channel_announcement(NULL, gossip_msg, + u8 *msg = towire_gossip_store_channel_announcement(ctx, gossip_msg, chan->satoshis); - gossip_store_append(gs, msg); - tal_free(msg); + return msg; } -static void gossip_store_add_channel_update(struct gossip_store *gs, - const u8 *gossip_msg) +/** + * Wrap the raw gossip message and write it to fd + * + * @param fd File descriptor to write the wrapped message into + * @param gossip_msg The message to write + * @return true if the message was wrapped and written + */ +static bool gossip_store_append(int fd, struct routing_state *rstate, const u8 *gossip_msg) { - u8 *msg = towire_gossip_store_channel_update(NULL, gossip_msg); - gossip_store_append(gs, msg); - tal_free(msg); + int t = fromwire_peektype(gossip_msg); + u32 msglen; + beint32_t checksum, belen; + const u8 *msg; + + if (t == WIRE_CHANNEL_ANNOUNCEMENT) + msg = gossip_store_wrap_channel_announcement(tmpctx, rstate, gossip_msg); + else if(t == WIRE_CHANNEL_UPDATE) + msg = towire_gossip_store_channel_update(tmpctx, gossip_msg); + else if(t == WIRE_NODE_ANNOUNCEMENT) + msg = towire_gossip_store_node_announcement(tmpctx, gossip_msg); + else if(t == WIRE_GOSSIP_LOCAL_ADD_CHANNEL) + msg = towire_gossip_store_local_add_channel(tmpctx, gossip_msg); + else if(t == WIRE_GOSSIP_STORE_CHANNEL_DELETE) + msg = gossip_msg; + else { + status_trace("Unexpected message passed to gossip_store: %s", + wire_type_name(t)); + return false; + } + + msglen = tal_len(msg); + belen = cpu_to_be32(msglen); + checksum = cpu_to_be32(crc32c(0, msg, msglen)); + + return (write(fd, &belen, sizeof(belen)) == sizeof(belen) && + write(fd, &checksum, sizeof(checksum)) == sizeof(checksum) && + write(fd, msg, msglen) == msglen); } -static void gossip_store_add_node_announcement(struct gossip_store *gs, - const u8 *gossip_msg) +void gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg) { - u8 *msg = towire_gossip_store_node_announcement(NULL, gossip_msg); - gossip_store_append(gs, msg); - tal_free(msg); + size_t stale; + + /* Only give error message once. */ + if (gs->fd == -1) + return; + + if (!gossip_store_append(gs->fd, gs->rstate, gossip_msg)) { + status_broken("Failed writing to gossip store: %s", + strerror(errno)); + gs->fd = -1; + } + + gs->count++; + stale = gs->count - gs->broadcast->count; + if (gs->count >= 100 && stale * MAX_COUNT_TO_STALE_RATE > gs->count) { + /* FIXME(cdecker) Implement rewriting of gossip_store */ + } } void gossip_store_add_channel_delete(struct gossip_store *gs, const struct short_channel_id *scid) { u8 *msg = towire_gossip_store_channel_delete(NULL, scid); - gossip_store_append(gs, msg); - tal_free(msg); -} - -static void gossip_store_local_add_channel(struct gossip_store *gs, - const u8 *add_msg) -{ - u8 *msg = towire_gossip_store_local_add_channel(NULL, add_msg); - gossip_store_append(gs, msg); - tal_free(msg); -} - -void gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg) -{ - int t = fromwire_peektype(gossip_msg); - - if (t == WIRE_CHANNEL_ANNOUNCEMENT) - gossip_store_add_channel_announcement(gs, gossip_msg); - else if(t == WIRE_CHANNEL_UPDATE) - gossip_store_add_channel_update(gs, gossip_msg); - else if(t == WIRE_NODE_ANNOUNCEMENT) - gossip_store_add_node_announcement(gs, gossip_msg); - else if(t == WIRE_GOSSIP_LOCAL_ADD_CHANNEL) - gossip_store_local_add_channel(gs, gossip_msg); - else - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Unexpected message passed to gossip_store: %s", - wire_type_name(t)); + gossip_store_append(gs->fd, gs->rstate, msg); } void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs)