|
|
@ -106,47 +106,56 @@ struct gossip_store *gossip_store_new(struct routing_state *rstate) |
|
|
|
return gs; |
|
|
|
} |
|
|
|
|
|
|
|
/* Copy a whole message from one gossip_store to another. Returns
|
|
|
|
* total msg length including header, or 0 on error. */ |
|
|
|
static size_t copy_message(int in_fd, int out_fd, unsigned offset) |
|
|
|
/* Returns bytes transferred, or 0 on error */ |
|
|
|
static size_t transfer_store_msg(int from_fd, size_t from_off, int to_fd, |
|
|
|
int *type) |
|
|
|
{ |
|
|
|
beint32_t belen, becsum; |
|
|
|
beint32_t hdr[2]; |
|
|
|
u32 msglen; |
|
|
|
u8 *msg; |
|
|
|
const u8 *p; |
|
|
|
size_t tmplen; |
|
|
|
|
|
|
|
/* FIXME: optimize both read and allocation */ |
|
|
|
if (lseek(in_fd, offset, SEEK_SET) < 0 |
|
|
|
|| read(in_fd, &belen, sizeof(belen)) != sizeof(belen) |
|
|
|
|| read(in_fd, &becsum, sizeof(becsum)) != sizeof(becsum)) { |
|
|
|
status_broken("Failed reading header from to gossip store @%u" |
|
|
|
*type = -1; |
|
|
|
if (pread(from_fd, hdr, sizeof(hdr), from_off) != sizeof(hdr)) { |
|
|
|
status_broken("Failed reading header from to gossip store @%zu" |
|
|
|
": %s", |
|
|
|
offset, strerror(errno)); |
|
|
|
from_off, strerror(errno)); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
msglen = be32_to_cpu(belen); |
|
|
|
msg = tal_arr(NULL, u8, sizeof(belen) + sizeof(becsum) + msglen); |
|
|
|
memcpy(msg, &belen, sizeof(belen)); |
|
|
|
memcpy(msg + sizeof(belen), &becsum, sizeof(becsum)); |
|
|
|
if (read(in_fd, msg + sizeof(belen) + sizeof(becsum), msglen) |
|
|
|
msglen = be32_to_cpu(hdr[0]); |
|
|
|
if (msglen & GOSSIP_STORE_LEN_DELETED_BIT) { |
|
|
|
status_broken("Can't transfer deleted msg from gossip store @%zu", |
|
|
|
from_off); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* FIXME: Reuse buffer? */ |
|
|
|
msg = tal_arr(tmpctx, u8, sizeof(hdr) + msglen); |
|
|
|
memcpy(msg, hdr, sizeof(hdr)); |
|
|
|
if (pread(from_fd, msg + sizeof(hdr), msglen, from_off + sizeof(hdr)) |
|
|
|
!= msglen) { |
|
|
|
status_broken("Failed reading %u from to gossip store @%u" |
|
|
|
status_broken("Failed reading %u from to gossip store @%zu" |
|
|
|
": %s", |
|
|
|
msglen, offset, strerror(errno)); |
|
|
|
tal_free(msg); |
|
|
|
msglen, from_off, strerror(errno)); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
if (write(out_fd, msg, msglen + sizeof(belen) + sizeof(becsum)) |
|
|
|
!= msglen + sizeof(belen) + sizeof(becsum)) { |
|
|
|
if (write(to_fd, msg, msglen + sizeof(hdr)) != msglen + sizeof(hdr)) { |
|
|
|
status_broken("Failed writing to gossip store: %s", |
|
|
|
strerror(errno)); |
|
|
|
tal_free(msg); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Can't use peektype here, since we have header on front */ |
|
|
|
p = msg + sizeof(hdr); |
|
|
|
tmplen = msglen; |
|
|
|
*type = fromwire_u16(&p, &tmplen); |
|
|
|
if (!p) |
|
|
|
*type = -1; |
|
|
|
tal_free(msg); |
|
|
|
return msglen + sizeof(belen) + sizeof(becsum); |
|
|
|
return sizeof(hdr) + msglen; |
|
|
|
} |
|
|
|
|
|
|
|
/* Local unannounced channels don't appear in broadcast map, but we need to
|
|
|
@ -177,12 +186,15 @@ static bool add_local_unnannounced(int in_fd, int out_fd, |
|
|
|
|
|
|
|
for (size_t i = 0; i < 2; i++) { |
|
|
|
size_t len_with_header; |
|
|
|
int type; |
|
|
|
|
|
|
|
if (!is_halfchan_defined(&c->half[i])) |
|
|
|
continue; |
|
|
|
|
|
|
|
len_with_header = copy_message(in_fd, out_fd, |
|
|
|
c->half[i].bcast.index); |
|
|
|
len_with_header = transfer_store_msg(in_fd, |
|
|
|
c->half[i].bcast.index, |
|
|
|
out_fd, |
|
|
|
&type); |
|
|
|
if (!len_with_header) |
|
|
|
return false; |
|
|
|
|
|
|
@ -195,58 +207,6 @@ static bool add_local_unnannounced(int in_fd, int out_fd, |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
/* Returns bytes transferred, or 0 on error */ |
|
|
|
static size_t transfer_store_msg(int from_fd, size_t from_off, int to_fd, |
|
|
|
int *type) |
|
|
|
{ |
|
|
|
beint32_t hdr[2]; |
|
|
|
u32 msglen; |
|
|
|
u8 *msg; |
|
|
|
const u8 *p; |
|
|
|
size_t tmplen; |
|
|
|
|
|
|
|
*type = -1; |
|
|
|
if (pread(from_fd, hdr, sizeof(hdr), from_off) != sizeof(hdr)) { |
|
|
|
status_broken("Failed reading header from to gossip store @%zu" |
|
|
|
": %s", |
|
|
|
from_off, strerror(errno)); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
msglen = be32_to_cpu(hdr[0]); |
|
|
|
if (msglen & GOSSIP_STORE_LEN_DELETED_BIT) { |
|
|
|
status_broken("Can't transfer deleted msg from gossip store @%zu", |
|
|
|
from_off); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* FIXME: Reuse buffer? */ |
|
|
|
msg = tal_arr(tmpctx, u8, sizeof(hdr) + msglen); |
|
|
|
memcpy(msg, hdr, sizeof(hdr)); |
|
|
|
if (pread(from_fd, msg + sizeof(hdr), msglen, from_off + sizeof(hdr)) |
|
|
|
!= msglen) { |
|
|
|
status_broken("Failed reading %u from to gossip store @%zu" |
|
|
|
": %s", |
|
|
|
msglen, from_off, strerror(errno)); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
if (write(to_fd, msg, msglen + sizeof(hdr)) != msglen + sizeof(hdr)) { |
|
|
|
status_broken("Failed writing to gossip store: %s", |
|
|
|
strerror(errno)); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Can't use peektype here, since we have header on front */ |
|
|
|
p = msg + sizeof(hdr); |
|
|
|
tmplen = msglen; |
|
|
|
*type = fromwire_u16(&p, &tmplen); |
|
|
|
if (!p) |
|
|
|
*type = -1; |
|
|
|
tal_free(msg); |
|
|
|
return sizeof(hdr) + msglen; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* Rewrite the on-disk gossip store, compacting it along the way |
|
|
|
* |
|
|
|