mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
test_protocol: fix --svg
Had bitrotted, and was completely broken with recent changes. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
ba50776c47
commit
3e34d50339
@ -16,12 +16,13 @@
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define A_LINEX 50
|
||||
#define B_LINEX 195
|
||||
#define A_TEXTX 45
|
||||
#define B_TEXTX 200
|
||||
#define A_LINEX 100
|
||||
#define B_LINEX 245
|
||||
#define A_TEXTX 95
|
||||
#define B_TEXTX 250
|
||||
|
||||
#define LINE_HEIGHT 5
|
||||
#define TEXT_HEIGHT 4
|
||||
#define STEP_HEIGHT 10
|
||||
#define LETTER_WIDTH 3
|
||||
|
||||
@ -202,8 +203,7 @@ struct peer {
|
||||
int infd, outfd, cmdfd, cmddonefd;
|
||||
|
||||
/* For drawing svg */
|
||||
char *text;
|
||||
char *io;
|
||||
char *info;
|
||||
|
||||
/* All htlcs. */
|
||||
struct htlc **htlcs;
|
||||
@ -240,13 +240,20 @@ static struct htlc *new_htlc(struct peer *peer, unsigned int htlc_id, int side)
|
||||
return peer->htlcs[n];
|
||||
}
|
||||
|
||||
static void htlc_changestate(struct htlc *htlc,
|
||||
static void htlc_changestate(struct peer *peer,
|
||||
struct htlc *htlc,
|
||||
enum htlc_state old,
|
||||
enum htlc_state new)
|
||||
{
|
||||
if (htlc->state != old)
|
||||
errx(1, "htlc was in state %s not %s",
|
||||
htlc_statename(htlc->state), htlc_statename(old));
|
||||
if (htlc->id)
|
||||
tal_append_fmt(&peer->info, "%u:%s\n",
|
||||
htlc->id, htlc_statename(new));
|
||||
else
|
||||
tal_append_fmt(&peer->info, "FEE:%s\n",
|
||||
htlc_statename(new));
|
||||
htlc->state = new;
|
||||
}
|
||||
|
||||
@ -265,7 +272,7 @@ static bool change_htlcs_(struct peer *peer,
|
||||
size_t t;
|
||||
for (t = 0; t < n_table; t++) {
|
||||
if (peer->htlcs[i]->state == table[t].from) {
|
||||
htlc_changestate(peer->htlcs[i],
|
||||
htlc_changestate(peer, peer->htlcs[i],
|
||||
table[t].from, table[t].to);
|
||||
changed = true;
|
||||
break;
|
||||
@ -404,12 +411,34 @@ static void read_peer(struct peer *peer, const char *str, const char *cmd)
|
||||
tal_free(p);
|
||||
}
|
||||
|
||||
static void PRINTF_FMT(2,3) record_send(struct peer *peer, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
tal_append_fmt(&peer->info, ">");
|
||||
tal_append_vfmt(&peer->info, fmt, ap);
|
||||
tal_append_fmt(&peer->info, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void PRINTF_FMT(2,3) record_recv(struct peer *peer, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
tal_append_fmt(&peer->info, "<");
|
||||
tal_append_vfmt(&peer->info, fmt, ap);
|
||||
tal_append_fmt(&peer->info, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void send_offer(struct peer *peer, unsigned int htlc)
|
||||
{
|
||||
struct htlc *h = new_htlc(peer, htlc, OURS);
|
||||
|
||||
htlc_changestate(h, NONEXISTENT, SENT_ADD_HTLC);
|
||||
tal_append_fmt(&peer->io, "add_htlc %u", htlc);
|
||||
htlc_changestate(peer, h, NONEXISTENT, SENT_ADD_HTLC);
|
||||
record_send(peer, "add_htlc %u", htlc);
|
||||
write_out(peer->outfd, "+", 1);
|
||||
write_out(peer->outfd, &htlc, sizeof(htlc));
|
||||
}
|
||||
@ -421,9 +450,9 @@ static void send_remove(struct peer *peer, unsigned int htlc)
|
||||
if (!h)
|
||||
errx(1, "send_remove: htlc %u does not exist", htlc);
|
||||
|
||||
htlc_changestate(h, RECV_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC);
|
||||
htlc_changestate(peer, h, RECV_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC);
|
||||
|
||||
tal_append_fmt(&peer->io, "fulfill_htlc %u", htlc);
|
||||
record_send(peer, "fulfill_htlc %u", htlc);
|
||||
write_out(peer->outfd, "-", 1);
|
||||
write_out(peer->outfd, &htlc, sizeof(htlc));
|
||||
}
|
||||
@ -432,8 +461,8 @@ static void send_feechange(struct peer *peer)
|
||||
{
|
||||
struct htlc *fee = new_htlc(peer, 0, OURS);
|
||||
|
||||
htlc_changestate(fee, NONEXISTENT, SENT_ADD_HTLC);
|
||||
tal_append_fmt(&peer->io, "update_fee");
|
||||
htlc_changestate(peer, fee, NONEXISTENT, SENT_ADD_HTLC);
|
||||
record_send(peer, "update_fee");
|
||||
write_out(peer->outfd, "F", 1);
|
||||
}
|
||||
|
||||
@ -477,7 +506,7 @@ static void send_commit(struct peer *peer)
|
||||
if (peer->remote->prev && !peer->remote->prev->revoked)
|
||||
errx(1, "commit: must wait for previous commit");
|
||||
|
||||
tal_append_fmt(&peer->io, "update_commit");
|
||||
record_send(peer, "update_commit");
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
@ -524,7 +553,7 @@ static void receive_revoke(struct peer *peer, u32 number)
|
||||
if (ci != peer->remote->prev)
|
||||
errx(1, "receive_revoke: always revoke previous?");
|
||||
|
||||
tal_append_fmt(&peer->io, "<");
|
||||
record_recv(peer, "update_revocation");
|
||||
ci->revoked = true;
|
||||
if (!ci->counterparty_signed)
|
||||
errx(1, "receive_revoke: revoked unsigned commit?");
|
||||
@ -542,8 +571,8 @@ static void receive_offer(struct peer *peer, unsigned int htlc)
|
||||
{
|
||||
struct htlc *h = new_htlc(peer, htlc, THEIRS);
|
||||
|
||||
htlc_changestate(h, NONEXISTENT, RECV_ADD_HTLC);
|
||||
tal_append_fmt(&peer->io, "<");
|
||||
htlc_changestate(peer, h, NONEXISTENT, RECV_ADD_HTLC);
|
||||
record_recv(peer, "add_htlc %u", h->id);
|
||||
}
|
||||
|
||||
/* BOLT #2:
|
||||
@ -558,8 +587,8 @@ static void receive_remove(struct peer *peer, unsigned int htlc)
|
||||
if (!h)
|
||||
errx(1, "recv_remove: htlc %u does not exist", htlc);
|
||||
|
||||
htlc_changestate(h, SENT_ADD_ACK_REVOCATION, RECV_REMOVE_HTLC);
|
||||
tal_append_fmt(&peer->io, "<");
|
||||
htlc_changestate(peer, h, SENT_ADD_ACK_REVOCATION, RECV_REMOVE_HTLC);
|
||||
record_recv(peer, "fulfill_htlc %u", h->id);
|
||||
}
|
||||
|
||||
/* BOLT #2:
|
||||
@ -571,8 +600,8 @@ static void receive_feechange(struct peer *peer)
|
||||
{
|
||||
struct htlc *fee = new_htlc(peer, 0, THEIRS);
|
||||
|
||||
htlc_changestate(fee, NONEXISTENT, RECV_ADD_HTLC);
|
||||
tal_append_fmt(&peer->io, "<");
|
||||
htlc_changestate(peer, fee, NONEXISTENT, RECV_ADD_HTLC);
|
||||
record_recv(peer, "update_fee");
|
||||
}
|
||||
|
||||
/* Send revoke.
|
||||
@ -586,7 +615,7 @@ static void send_revoke(struct peer *peer, struct commit_info *ci)
|
||||
{ RECV_ADD_COMMIT, SENT_ADD_REVOCATION },
|
||||
{ RECV_REMOVE_ACK_COMMIT, SENT_REMOVE_ACK_REVOCATION }
|
||||
};
|
||||
tal_append_fmt(&peer->io, "update_revocation");
|
||||
record_send(peer, "update_revocation");
|
||||
|
||||
/* We always revoke in order. */
|
||||
assert(!ci->prev || ci->prev->revoked);
|
||||
@ -615,7 +644,7 @@ static void receive_commit(struct peer *peer, const struct signature *sig)
|
||||
{ RECV_REMOVE_REVOCATION, RECV_REMOVE_ACK_COMMIT }
|
||||
};
|
||||
|
||||
tal_append_fmt(&peer->io, "<");
|
||||
record_recv(peer, "update_commit");
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
@ -635,8 +664,6 @@ static void receive_commit(struct peer *peer, const struct signature *sig)
|
||||
peer->local = new_commit_info(peer, peer->local);
|
||||
peer->local->counterparty_signed = true;
|
||||
|
||||
/* This is the one case where we send without a command. */
|
||||
tal_append_fmt(&peer->text, "\n");
|
||||
send_revoke(peer, peer->local->prev);
|
||||
}
|
||||
|
||||
@ -646,7 +673,6 @@ static void do_cmd(struct peer *peer)
|
||||
int i;
|
||||
unsigned int htlc;
|
||||
struct commit_info *ci;
|
||||
struct iovec iov[2];
|
||||
|
||||
i = read(peer->cmdfd, cmd, sizeof(cmd)-1);
|
||||
if (cmd[i-1] != '\0')
|
||||
@ -657,8 +683,7 @@ static void do_cmd(struct peer *peer)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
peer->io = tal_strdup(peer, "");
|
||||
peer->text = tal_strdup(peer->io, "");
|
||||
peer->info = tal_strdup(peer, "");
|
||||
|
||||
if (sscanf(cmd, "offer %u", &htlc) == 1)
|
||||
send_offer(peer, htlc);
|
||||
@ -704,12 +729,7 @@ static void do_cmd(struct peer *peer)
|
||||
} else
|
||||
errx(1, "Unknown command %s", cmd);
|
||||
|
||||
iov[0].iov_base = peer->io;
|
||||
iov[0].iov_len = strlen(peer->io)+1;
|
||||
iov[1].iov_base = peer->text;
|
||||
iov[1].iov_len = strlen(peer->text)+1;
|
||||
writev(peer->cmddonefd, iov, 2);
|
||||
tal_free(peer->io);
|
||||
write(peer->cmddonefd, peer->info, strlen(peer->info)+1);
|
||||
|
||||
/* We must always have (at least one) signed, unrevoked commit. */
|
||||
for (ci = peer->local; ci; ci = ci->prev) {
|
||||
@ -772,12 +792,16 @@ static void add_sent(struct sent **sent, int y, const char *msg)
|
||||
}
|
||||
|
||||
static void draw_line(char **str,
|
||||
int old_x, struct sent **sent, int new_x, int new_y)
|
||||
int old_x, struct sent **sent, const char *what,
|
||||
int new_x, int new_y)
|
||||
{
|
||||
size_t n = tal_count(*sent);
|
||||
if (n == 0)
|
||||
errx(1, "Receive without send?");
|
||||
|
||||
if (!streq((*sent)->desc, what))
|
||||
errx(1, "Received %s but sent %s?", what, (*sent)->desc);
|
||||
|
||||
tal_append_fmt(str, "<line x1=\"%i\" y1=\"%i\" x2=\"%i\" y2=\"%i\" marker-end=\"url(#tri)\" stroke=\"black\" stroke-width=\"0.5\"/>\n",
|
||||
old_x, (*sent)[0].y - LINE_HEIGHT/2,
|
||||
new_x, new_y - LINE_HEIGHT/2);
|
||||
@ -790,44 +814,93 @@ static void draw_line(char **str,
|
||||
tal_resize(sent, n-1);
|
||||
}
|
||||
|
||||
static void append_text(char **svg, bool is_a, int *y, char *text,
|
||||
static bool append_text(char **svg, bool is_a, int *y, const char *text,
|
||||
size_t *max_chars)
|
||||
{
|
||||
char *eol;
|
||||
|
||||
eol = strchr(text, '\n');
|
||||
if (eol)
|
||||
*eol = '\0';
|
||||
char **texts = tal_strsplit(NULL, text, "\n", STR_NO_EMPTY);
|
||||
size_t i;
|
||||
|
||||
tal_append_fmt(svg,
|
||||
"<text x=\"%i\" y=\"%i\" text-anchor=\"%s\" "TEXT_STYLE">%s</text>",
|
||||
is_a ? A_TEXTX : B_TEXTX, *y,
|
||||
is_a ? "end" : "start",
|
||||
text);
|
||||
if (strlen(text) > *max_chars)
|
||||
*max_chars = strlen(text);
|
||||
if (tal_count(texts) == 1)
|
||||
return false;
|
||||
|
||||
if (eol) {
|
||||
*y += LINE_HEIGHT;
|
||||
append_text(svg, is_a, y, eol+1, max_chars);
|
||||
for (i = 0; i < tal_count(texts) - 1; i++) {
|
||||
tal_append_fmt(svg,
|
||||
"<text x=\"%i\" y=\"%i\" text-anchor=\"%s\" "TEXT_STYLE">%s</text>",
|
||||
is_a ? A_TEXTX : B_TEXTX, *y,
|
||||
is_a ? "end" : "start",
|
||||
texts[i]);
|
||||
*y += TEXT_HEIGHT;
|
||||
if (strlen(texts[i]) > *max_chars)
|
||||
*max_chars = strlen(texts[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool process_output(char **svg, bool is_a, const char *output,
|
||||
struct sent **a_sent, struct sent **b_sent,
|
||||
int *y, size_t *max_chars)
|
||||
{
|
||||
/* We can recv and send for recvcommit */
|
||||
char **outputs = tal_strsplit(NULL, output, "\n", STR_NO_EMPTY);
|
||||
size_t i;
|
||||
|
||||
if (tal_count(outputs) == 1)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < tal_count(outputs)-1; i++) {
|
||||
if (strstarts(outputs[i], "<")) {
|
||||
if (is_a)
|
||||
draw_line(svg, B_LINEX, b_sent, outputs[i]+1,
|
||||
A_LINEX, *y);
|
||||
else
|
||||
draw_line(svg, A_LINEX, a_sent, outputs[i]+1,
|
||||
B_LINEX, *y);
|
||||
} else if (strstarts(outputs[i], ">")) {
|
||||
if (is_a)
|
||||
add_sent(a_sent, *y, outputs[i]+1);
|
||||
else
|
||||
add_sent(b_sent, *y, outputs[i]+1);
|
||||
} else {
|
||||
append_text(svg, is_a, y, outputs[i], max_chars);
|
||||
}
|
||||
}
|
||||
*y += STEP_HEIGHT;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool get_output(int donefd, char **svg, bool is_a,
|
||||
struct sent **a_sent, struct sent **b_sent,
|
||||
int *y, size_t *max_chars)
|
||||
{
|
||||
char output[200];
|
||||
int r;
|
||||
|
||||
alarm(5);
|
||||
/* FIXME: Assumes large pipebuf, atomic read */
|
||||
r = read(donefd, output, sizeof(output)-1);
|
||||
if (r <= 0)
|
||||
return false;
|
||||
output[r] = '\0';
|
||||
alarm(0);
|
||||
|
||||
if (*svg)
|
||||
process_output(svg, is_a, output, a_sent, b_sent, y, max_chars);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char cmd[80], output[200], *svg = tal_strdup(NULL, "");
|
||||
char cmd[80], *svg = NULL;
|
||||
int a_to_b[2], b_to_a[2], acmd[2], bcmd[2], adonefd[2], bdonefd[2];
|
||||
int y = STEP_HEIGHT + LINE_HEIGHT;
|
||||
struct sent *a_sent = tal_arr(NULL, struct sent, 0),
|
||||
*b_sent = tal_arr(NULL, struct sent, 0);
|
||||
bool output_svg = false;
|
||||
size_t max_chars = 0;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
if (argv[1] && streq(argv[1], "--svg"))
|
||||
output_svg = true;
|
||||
svg = tal_strdup(NULL, "");
|
||||
|
||||
if (pipe(a_to_b) || pipe(b_to_a) || pipe(adonefd) || pipe(acmd))
|
||||
err(1, "Creating pipes");
|
||||
@ -849,8 +922,7 @@ int main(int argc, char *argv[])
|
||||
close(a_to_b[1]);
|
||||
|
||||
while (fgets(cmd, sizeof(cmd), stdin)) {
|
||||
int cmdfd, donefd, r;
|
||||
char *io, *text;
|
||||
int cmdfd, donefd;
|
||||
|
||||
if (!strends(cmd, "\n"))
|
||||
errx(1, "Truncated command");
|
||||
@ -863,7 +935,7 @@ int main(int argc, char *argv[])
|
||||
cmdfd = bcmd[1];
|
||||
donefd = bdonefd[0];
|
||||
} else if (strstarts(cmd, "echo ")) {
|
||||
if (!output_svg) {
|
||||
if (!svg) {
|
||||
printf("%s\n", cmd + 5);
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -889,45 +961,14 @@ int main(int argc, char *argv[])
|
||||
errx(1, "Unknown command %s", cmd);
|
||||
|
||||
/* Don't dump if outputting svg. */
|
||||
if (output_svg && strstarts(cmd+2, "dump"))
|
||||
if (svg && strstarts(cmd+2, "dump"))
|
||||
continue;
|
||||
|
||||
if (!write_all(cmdfd, cmd+2, strlen(cmd)-1))
|
||||
errx(1, "Sending %s", cmd);
|
||||
|
||||
alarm(5);
|
||||
r = read(donefd, output, sizeof(output)-2);
|
||||
if (r <= 0)
|
||||
errx(1, "Failed on cmd %s", cmd);
|
||||
output[r] = output[r+1] = '\0';
|
||||
io = output;
|
||||
text = output + strlen(output) + 1;
|
||||
if (r != strlen(text) + strlen(io) + 2)
|
||||
errx(1, "Not nul-terminated: %s+%s gave %zi not %u",
|
||||
io, text, strlen(text) + strlen(io) + 2, r);
|
||||
alarm(0);
|
||||
|
||||
/* We can recv and send for recvcommit */
|
||||
if (strstarts(io, "<")) {
|
||||
if (strstarts(cmd, "A:"))
|
||||
draw_line(&svg, B_LINEX, &b_sent, A_LINEX, y);
|
||||
else
|
||||
draw_line(&svg, A_LINEX, &a_sent, B_LINEX, y);
|
||||
memmove(io, io+1, strlen(io));
|
||||
}
|
||||
if (!streq(io, "")) {
|
||||
if (strstarts(cmd, "A:"))
|
||||
add_sent(&a_sent, y, io);
|
||||
else
|
||||
add_sent(&b_sent, y, io);
|
||||
}
|
||||
if (!streq(text, "") && output_svg) {
|
||||
append_text(&svg,
|
||||
strstarts(cmd, "A:"),
|
||||
&y,
|
||||
text,
|
||||
&max_chars);
|
||||
}
|
||||
get_output(donefd, &svg, strstarts(cmd, "A:"),
|
||||
&a_sent, &b_sent, &y, &max_chars);
|
||||
}
|
||||
|
||||
write_all(acmd[1], "", 1);
|
||||
@ -940,7 +981,7 @@ int main(int argc, char *argv[])
|
||||
errx(1, "Response after sending exit command");
|
||||
alarm(0);
|
||||
|
||||
if (output_svg)
|
||||
if (svg)
|
||||
printf("<svg width=\"%zu\" height=\"%u\">\n"
|
||||
"<marker id=\"tri\" "
|
||||
"viewBox=\"0 0 5 5\" refX=\"0\" refY=\"5\" "
|
||||
|
Loading…
Reference in New Issue
Block a user