common/gossip_store: expose routine to read one header.

This is useful when you're writing routines to scan it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2023-01-30 16:54:16 +10:30 committed by Alex Myers
parent 0274d88bad
commit 7e8b93daa1
2 changed files with 56 additions and 12 deletions

View File

@ -182,25 +182,48 @@ u8 *gossip_store_next(const tal_t *ctx,
return msg;
}
size_t find_gossip_store_end(int gossip_store_fd, size_t off)
{
/* We cheat and read first two bytes of message too. */
struct {
struct hdr_and_type {
struct gossip_hdr hdr;
be16 type;
} buf;
};
/* Beware padding! */
#define HDR_AND_TYPE_SIZE (sizeof(struct gossip_hdr) + sizeof(u16))
bool gossip_store_readhdr(int gossip_store_fd, size_t off,
size_t *len,
u32 *timestamp,
u16 *flags,
u16 *type)
{
struct hdr_and_type buf;
int r;
while ((r = pread(gossip_store_fd, &buf,
sizeof(buf.hdr) + sizeof(buf.type), off))
== sizeof(buf.hdr) + sizeof(buf.type)) {
u16 msglen = be16_to_cpu(buf.hdr.len);
r = pread(gossip_store_fd, &buf, HDR_AND_TYPE_SIZE, off);
if (r != HDR_AND_TYPE_SIZE)
return false;
*len = be16_to_cpu(buf.hdr.len);
if (flags)
*flags = be16_to_cpu(buf.hdr.flags);
if (timestamp)
*timestamp = be32_to_cpu(buf.hdr.timestamp);
if (type)
*type = be16_to_cpu(buf.type);
return true;
}
size_t find_gossip_store_end(int gossip_store_fd, size_t off)
{
size_t msglen;
u16 type;
while (gossip_store_readhdr(gossip_store_fd, off,
&msglen, NULL, NULL, &type)) {
/* Don't swallow end marker! */
if (buf.type == CPU_TO_BE16(WIRE_GOSSIP_STORE_ENDED))
if (type == WIRE_GOSSIP_STORE_ENDED)
break;
off += sizeof(buf.hdr) + msglen;
off += sizeof(struct gossip_hdr) + msglen;
}
return off;
}

View File

@ -69,6 +69,27 @@ u8 *gossip_store_next(const tal_t *ctx,
bool with_spam,
size_t *off, size_t *end);
/**
* Direct store accessor: read gossip msg hdr from store.
* @gossip_store_fd: the readable file descriptor
* @off: the offset to read
* @len (out): the length of the message (not including header)
* @timestamp (out): if non-NULL, set to the timestamp.
* @flags (out): if non-NULL, set to the flags.
* @type (out): if non-NULL, set to the msg type.
*
* Returns false if there are no more gossip msgs. If you
* want to read the message, use gossip_store_next, if you
* want to skip, simply add sizeof(gossip_hdr) + *len to *off.
* Note: it's possible that entire record isn't there yet,
* so gossip_store_next can fail.
*/
bool gossip_store_readhdr(int gossip_store_fd, size_t off,
size_t *len,
u32 *timestamp,
u16 *flags,
u16 *type);
/**
* Gossipd will be writing to this, and it's not atomic! Safest
* way to find the "end" is to walk through.